zoukankan      html  css  js  c++  java
  • Python语法速查: 6. 循环与迭代

    返回目录

    本篇索引

    (1)while循环与for循环

    (2)一些迭代工具

    (3)列表推导与序列解包

    (4)迭代器

     (1)while循环与for循环

    while仅能用于普通循环,而for除了可以做循环外,还可以遍历序列、集合、字典、迭代器等。

    需要注意的是,在类似:for i in somelist: 的循环中,迭代变量 i 的作用域并非for语句私有,循环结束后迭代变量依然保留最后一个值。有时候for可以用于直接迭代对象,如下2个例子所示:

    直接迭代字典

    for key in d:    # 直接对字典进行迭代相当于 for key in d.keys():
        print(key, d[key])

    直接迭代文件

    f = open('a.txt')
    for line in f:    # 迭代文件对象中的每一行
        print(line)

    ● break

    可用于跳出while或for循环。break和下面的continue语句仅应用于正在执行的最内层循环,如果要跳出多层嵌套循环结构,可使用raise()抛出异常。

    ● continue

    结束本循环的当前轮,跳到本循环的下一轮开始。

    ● else

    与while或for循环配对的else代码段,仅在本循环中没有调用过break时执行。

    for i in range(0,100):
        if i > 100:
            break;
    else:
        print('running else.')
        
    # 结果为:running else.

      (2)一些迭代工具

    ● 并行迭代

    使用内建zip()函数,它可以把两个序列“压缩”在一起,返回一个元组列表。 当两个序列长度不等时,以短的那个迭代完就会停止。zip()还支持同时对多个(3个及以上)列表进行迭代。

    a = 'abc'
    b = [1,2,3]
    for x,y in zip(a,b):
        print(x,y)
    # 结果每次迭代依次显示:a 1、b 2、c 3

    以上代码相当于:

    for i in range(min(len(a),len(b)):
        print(a[i],b[i])

    ● 编号迭代

    使用内建的enumerate()函数,可以在迭代的同时,同时获取迭代的次数索引。

    a = 'abc'
    for i,x in enumerate(a):
        print('i=%d,x=%s' %(i,x)) 
    # 结果依次显示:i=0,x=a、i=1,x=b、i=2,x=c

      (3)列表推导与序列解包

    ● 列表推导(list comprehension)

    “列表推导”是利用for循环来快速创建新列表的一种方法。

    a. 基本用法:

    [ x运算表达式 for x in 迭代器 ]

    举例:

    [x*2 for x in range(5)]    # 结果生成新序列:[0,2,4,6,8]

    b. 条件判断用法:

    每次迭代时,只有当“条件表达式”的值为真时,才会对x进行运算,并将结果放入新序列。语法如下:

    [ x运算表达式 for x in 迭代器 if 条件表达式 ]

    举例:

    [x for x in range(10) if x%2]    # 取出range(10)范围内的所有奇数,结果为:[1,3,5,7,9]

    c. 完整用法:

    可以同时使用多个嵌套的for循环并对每个循环使用if条件表达式,语法如下:

    [ i_1,i_2,...,i_n运算表达式 for i_1 in iter1 if 条件表达式1 
                              for i_2 in iter2 if 条件表达式2
                              ...... 
                              for i_n in itern if 条件表达式n ]

    以上语法大致相当于如下等价代码:

    s = []
    for i_1 in iter1:
        if 条件表达式1:
            for i_2 in iter2:
                if 条件表达式2:
                    ......
                    for i_n in itern:
                        if 条件表达式n:
                            s.append(i_1,i_2,...,i_n运算表达式)

    举例:

    a = 'abc'
    b = [1,2,3]
    [(i1,i2) for i1 in a 
             for i2 in b if i2 % 2]    
    # 结果为:[('a',1), ('a',3), ('b',1), ('b',3), ('c',1), ('c',3) ]

    ● 迭代序列解包(sequence unpacking)

    当可迭代对象返回元组时,这个特性比较有用。例如需要获取字典中的键-值对时,可使用序列解包方法:

    for k,v in d.items():   # 每次循环同时取出字典中的键与值,分别放入k与v中
        print(k,v)

      (4)迭代器

    可以使一个普通对象也支持迭代操作,此时需要为这个对象实现__iter__()方法和__next__()方法。

    ● __iter__()方法:

    本方法要求返回一个迭代器对象(通常可直接返回对象自身,详见下例)。

    ● __next__()方法:

    __next__()方法由刚才通过__iter__()方法返回的迭代器对象进行调用,其作用是计算并返回迭代的下一个对象。当迭代器已迭代完所有的内容时,__next__()方法应该引发一个StopIteration异常,以通知外部的调用者结束迭代。

    以下代码实现一个类似于 “列表[1,2,3,4,5]” 的迭代器:

    class MyIterator:
        v = 0
        def __iter__(self):
            return self
        def __next__(self):
            self.v += 1
            if self.v > 5:
                raise StopIteration
            return self.v
    
    myiter = MyIterator()
    for i in myiter:
        print(i)
        
    # 运行结果为,依次显示:1、2、3、4、5

    ● 迭代的外部原理:

    上例中,当运行for语句进行迭代时,等效于运行以下代码:

    _iter = myiter.__iter__()
    while 1:
        try:
            i = _iter.__next__()
        except StopIteration:
            break
        print(i)  # 本句即为 for 循环中用户自己写的循环内容

    从上面的代码中可以看到,迭代是使用__iter__()返回的对象来调用__next__()方法的,所以可以不一定是self。另外,内置函数iter()可以从可迭代的对象中获得迭代器,内置函数next()可以自动访问可迭代对象的__next__()方法。

    因此,上面的第1行和第4行语句可等效为:

    _iter = iter(s)    # 相当于 _iter = myiter.__iter__()
    i = next(_iter)    # 相当于 i = _iter.__next__(),甚至直接写成:i = next(myiter) 也是可以的

    ● 将迭代和序列互相转换:

    用list()的构造方法能显式地将迭代器转换为列,也能用内置函数iter()将序列转换为迭代器。

    # ......
    # 前面已定义MyIterator类
    
    myiter = MyIterator()
    s = list(myiter)
    print(s)
    
    # 结果为:[1,2,3,4,5]

    返回目录

  • 相关阅读:
    Java中Comparable与Comparator的区别
    LeetCode[5] 最长的回文子串
    LeetCode[3] Longest Substring Without Repeating Characters
    LeetCode 7. Reverse Integer
    统计单词出现的次数
    System.arraycopy()和Arrays.copyOf()的区别
    SyncToy
    查看端口占用及进程号
    TCP协议
    python 的日志logging模块学习
  • 原文地址:https://www.cnblogs.com/initcircuit/p/11695612.html
Copyright © 2011-2022 走看看