zoukankan      html  css  js  c++  java
  • Python中的Comprehensions和Generations

    Python中的Comprehensions和Generations语法都是用来迭代的。Comprehensions语法可用于list,set,dictionary上,而Generations语法分为Generator函数和Generator表达式。

    Comprehensions

    以list的Comprehensions语法为例:

    # 常规语法
    [expression for target in iterable]
    [x ** 2 for x in range(10)]
    
    # 加入if语句
    [expression for target in iterable if condiction]
    [x ** 2 for x in range(10) if x % 2 == 0]
    
    # 完整语法
    [expression for target1 in interable1 if condition1
                     for target2 in interable2 if condition2
                     for target3 in interable3 if condition3
                     ...
                    for targetN in iterableN if condictionN]
    [x + y + z for x in 'spam' if x in 'sm'
               for y in 'SPAM' if y in ('P', 'A')
               for z in '123' if z > '1']        

    通过Comprehensions的完整语法,可以发现,Comprehensions语法是允许嵌套的,它们等于嵌套的for循环:

    res = []
    
    for x in 'spam':
        if x in 'sm':
            for y in 'SPAM':
                if y in ('P', 'A'):
                    for z in '123':
                        if z > '1':
                            res.append[x + y + z]

    而set和dictionary的Comprehensions语法与list的Comprehensions语法类似,不同之处只在于,对于set来说,只需将list Comprehensions语法中的[]换成{};对于dictinary来说,除了将[]换成{},expression是由:分隔的两个表达式:

    >>>{x * x for x in range(10)}          # set的语法
    {0, 1, 4, 81, 64, 9, 16, 49, 25, 36}
    
    >>>{x: x * x for x in range(10)}    # dictionary的语法
    {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

    Generations

    Generations分为Generator函数和Generator表达式。

    1 Generator函数

    1) Generator函数的定义和普通函数定义一样,不同之处在于,Generator函数需要使用yield表达式。yield表达式的作用是告诉Python,当调用Generator函数时,返回的是一个迭代器。当遍历这个返回的迭代器时,Generator函数开始运行,当碰到yield表达式时,一方面将yield表达式的值返给迭代器,另一方面暂停Generator函数的执行;当下次遍历的时候,Generator函数继续运行yiled表达式后面的语句,这样周而复始,直到迭代完毕:

    def test():
        for i in range(5):
            yield i
            print('###')
    
    >>>G = test()          # 调用Generator函数返回的是一个迭代器
    >>>G
    <generator object test at 0x7f1246c1ee60>
    
    >>>next(G)           # 返回yield表达式的值,并在那里暂停
    0
    
    >>>next(G)          # 继续迭代,运行yield后面的语句,由于for循环,再次碰到yield语句,返回yield语句的值,并且再次暂停
    ###
    1
    
    >>>next(G)    # 继续迭代
    ###
    2
    
    >>> next(G)    # 继续迭代
    ###
    3
    
    >>>>next(G)   # 继续迭代
    ###
    4
    
    >>>next(G)   # 继续迭代,此时迭代结束
    ###             # print语句还是会执行
    Traceback (most rencent call last):
        File "<stdin>", line 1, in <module>
    StopInteration

    在Generator函数中也可以包含return语句,如果碰到return语句,迭代就会提前结束:

    def test():
        for i in range(5):
            return
            yield
            print('###')
    
    
    >>>G = test()   # 返回迭代器
    >>>G
    <generator object test at 0x7f1246c1eee08>
    
    >>>next(G)    # 遇到return语句,迭代提前结束
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    StopInteration

    2) send方法

    在Python 2.5之后,Generator函数返回的迭代器可以使用send方法。send方法也是遍历迭代器,不同之处是send方法允许传递一个值,而这个值会变成yield的返回值,从这个意义上将,yield此时是一个表达式,而不是一条语句:

    def test():
            for i range(5):
                X = (yied i) + 10   # 如果不加括号,等价于 X = yield (i + 10)
                print('%s %d' %('###', X))
    
    >>>G = test()
    >>>next(G)     # 必须首先调用next方法来启动迭代器
    0
    
    >>>G.send(77)
    ### 87
    1

    2 Generator表达式

    Generator表达式和list Comprehensions十分类似,区别就是将[]换成()就可以了,并且括号也不是必须的。如果Generator表达式已经被括号包围了,并且Generator表达式是括号里面的唯一表达式,那么就可以省略括号,否则,就需要使用:

    >>>sum(x ** 2 for x in range(4))    # 括号可以省略
    
    >>>sorted((x ** 2 for x in range(4)), reverse=True)    # 需要使用括号

    Scope

    在Python 3.X中,对于Comprehensions和Generator表达式自己生命的变量,该变量只能在Comprehensions和Generator表达式内部使用,外部无法访问这些变量;在Python 2.X中,规则基本和Python 3.X中一样,唯一的例外就是在Python 2.X中,list Comprehensions生命的变量,并不是只有list Comprehensions内部使用,外部也可以访问:

    >>>(X for X in range(5))   # Python 3.X , Python 2.X
    >>>X
    NameError: name 'X' is not defined
    
    >>>[X for X in range(5)] # Pyhon 3.X
    >>>X
    NameError: name 'X' is not defined
    
    
    >>>[X for X in range(5)]     # Pyhon 2.X
    >>>X                            # 可以访问
    4
  • 相关阅读:
    [linux1exe元旦特供]基于wine的IE6一键安装
    http://www.tianya.cn/publicforum/content/funinfo/1/1869814.shtml
    最全的design pattern 概述
    例解 autoconf 和 automake 生成 Makefile 文件
    根据条件分组SQL
    SQL Express自动备份
    通过asp.net 短信猫发短信
    EXT.NET GridPanel(按键事件带参的另一种写法)
    Asp.net操作IIS(调试通过)
    面向接口编程详解——编程实例(T2噬菌体)
  • 原文地址:https://www.cnblogs.com/chaoguo1234/p/9221201.html
Copyright © 2011-2022 走看看