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

原文地址:https://www.cnblogs.com/chaoguo1234/p/9221201.html

时间: 2024-07-30 04:28:52

Python中的Comprehensions和Generations的相关文章

走入计算机的第四十天(python中sockserver模块)

一.Python中的sockserver模块 1.该模块与sock模块不同之处是该模块自动帮我们分装好了一些功能,让我们在编程的时候直接调用这些功能就可以了,节省了编程步骤. 2.如图所示 注释:上图为服务端设置 该模块的操作方法比较死板,我们只要会熟悉的使用他就可以了.

python中if __name__ == &#39;__main__&#39;:

Using a module's __name__ Example? 8.2.? Using a module's __name__ #!/usr/bin/python # Filename: using_name.py if __name__ == '__main__': print 'This program is being run by itself' else: print 'I am being imported from another module' Output $ pytho

关于Python中的yield

关于Python中的yield http://www.cnblogs.com/tqsummer/archive/2010/12/27/1917927.html http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ 一.迭代器(iterator) 在Python中,for循环可以用于Python中的任何类型,包括列表.元祖等等,实际上,for循环可用于任何“可迭代对象”,这其实就是迭代器 迭代器是一个实现了迭代器协议

python中的那些“神器”

"武林至尊,宝刀屠龙,号令天下,莫敢不从,倚天不出,谁与争锋",这是神器.不过今天要说的python中的"神器"就没有这么厉害了,这里要说的"神器"其实就是名称里面带了个"器"的,如下: 列表解析器 迭代器 生成器 装饰器 列表解析器 现在遇到了这样一个问题需要解决:"有一个数字的列表,要求对该列表中的奇数乘以2,返回处理完成后的列表(不改变原来列表的顺序,仅对列表中的奇数乘以2)",比较传统的方法可能会是

Python中字符串格式化如何实现?

Python开发中字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存. This PEP proposes a new system for built-in string formatting operations, intended as a replacement for the existing '%' string formatting operator. 1.百分号方式 %[(na

python 中*args 和 **kwargs

简单的可以理解为python 中给函数传递的可变参数,args 是 列表的形式.kwargs 是 key,value的形式,也就是python 中的字典. *args 必须出现在**kwargs 的前边,否则会抛异常. 1 def test(*args, **kwargs): 2 print args 3 print kwargs 1 if __name__ == '__main__': 2 print '---test 1---' 3 test(1, 2, 3) 4 print '---tes

python中super出现的TypeError: must be type, not classobj 原因及解决

执行一下代码,出现错误,TypeError: must be type, not classobj class A():    def __init__(self):        print("Enter A")        print("Leave A") class B(A):    def __init__(self):        print("Enter B")        super(B, self).__init__()  

python中的切片问题

对于在一个字符串中选取几个字符,不同的语言有不同的解决方案,python 中就有了切片的方法.    在list中,如下:     s=list(range(1,101))    如果想要选取偶数个数字(或者选取偶数),可以用循环的方法:但是方法臃肿,比较"笨"    但是python中给出的切片方法是更加的优雅的,如下:    L=list(range(1,101))    print(L[0])    print(L[0:10])#输出结果是[1, 2, 3, 4, 5, 6, 7

Python学习-16.Python中的错误处理

虽然叫错误,但跟 C# 中的异常是一回事.只不过 Python 中叫错误(Error)而 C# 中叫异常(Exception). 先手工产生一个异常: 1 file = open('','r') 上面一句由于路径是空路径,因此文件肯定是不存在的,执行这一句会引发 FileNotFoundError 这个错误. 既然是错误的,程序也停止了,这是我们不希望的,因此得想办法处理一下. 在 Python 中,异常处理使用 try.except.finally 这三个关键字. 修改代码如下: 1 path