Python学习笔记(十九)- 推导式和生成式(Comprehensions and Generations)

1.将方括号【[]】中的列表推导式与小括号【()】括起来的有什么区别?
答:在方括号中的列表推导式在内存中会一次生成结果列表。当它们括在小括号中时,它们实际上是生成器表达式 - 它们具有相似的含义,但不会同时生成结果列表。相反,生成器表达式返回一个生成器对象,当在迭代上下文(iteration context)中使用时,它会在结果中一次生成一项。

 

2.生成器(generators)和迭代器(iterators)如何联系?
答:生成器是可自动支持迭代协议(iteration protocol)的可迭代对象(iterable objects) 。它们是具有带 __next__ 方法的迭代器(2.X中是 next 方法),它反复向前推进一系列结果中的下一项,并在一系列结果结束时引发异常【StopIteration】。在Python中,我们可以使用def和yield编写生成器函数,使用带括号的推导式来生成生成器表达式,使用定义名为__iter__ 的特殊方法的类来生成生成器对象(在本书后面讨论)。

 

3.如何判断函数是否为生成函数?
答:生成器函数在其代码中的某处有一个 yield 语句。生成器函数在语法上与普通函数相同,但它们是由Python专门编译的,以便在调用时返回可迭代的生成器对象。该对象保留值之间的状态和代码位置。

 

4.yield语句是干什么的?
答:当存在 yield 语句时,该语句使 Python 专门编译函数作为生成器;在函数调用时,该函数返回一个支持迭代协议的生成器对象。运行 yield 语句时,它会将结果发送回调用者(caller)并暂停(suspend)函数的状态;然后,可以在最后的 yield 语句之后恢复该函数,以响应调用者发出的下一个内置函数 next 或 __next__ 方法的调用。在更高级的角色中,生成器的 send 方法类似地恢复生成器,但也可以传递一个值,以代表yield表达式的值(通俗地讲,yield语句运行时会有一个值,可以赋给某个变量)。生成器函数也可以有一个 return 语句,它会终止生成器。

>>>def gen():
        for i in range(10):
            X = yield i
            print(X)
>>>G = gen()
>>>next(G)        #这里要注意一定要先启动生成器,具体原因百度一下
0
>>>G.send(77)     #继续向前产生值,把值送给yield表达式
77
1

 

5.map调用和列表推导式如何联系? 比较和对比两者。
答:map 调用类似于列表推导式 - 两者都产生一系列值,通过收集对一个序列中的每个项或其他可迭代对象的应用操作的结果,一次产生一项。主要区别在于 map 对每个项应用函数调用,列表推导应用任意表达式。因为这个原因,列表推导式更加通用;它可以应用像 map 这样的函数调用表达式,但 map 需要一个函数来应用其他类型的表达式。列表推导还支持扩展语法,例如嵌套 for 循环和 if 子句,可以实现像内置函数 filter 的功能。在 Python 3.X中,map也有所不同,它产生了值的生成器;列表推导一次性地在内存中实现结果列表。在2.X中,两个工具都会创建结果的列表。

 

一些其它的东西:

简单模式:[expression for target in iterable]

复杂模式:[expression for target1 in iterable1 if condition1

                                      for target2 in iterable2 if condition2...

                                       for targetN in iterableN if conditionN]

列表推导式的一些应用:

>>>M = [[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]]
>>>[row[0] for row in M] #第一列
[1, 4, 7]
>>>[M[i][i] for i in range(len(M))] #取对角线
[1, 5, 9]
>>>[M[i][len(M)-1-i] for i in range(len(M))] #取反对角线
[3, 5, 7]

zip函数的实现

>>>def mymapPad(*seqs, pad=None):
    seqs = [list(s) for s in seqs]
    res = []
    while any(seqs):
        res.append(tuple(s.pop(0) if s else pad for s in seqs))
    return res

>>>S1, S2 = 'abc', 'xyz123'
>>>print(mymapPad(S1, S2, pad=99))
    
>>>def myzip(*args):
    iters = list(map(iter, args)) #Python 2.X 去掉list函数
    while iters:
        res = [next(i) for i in iters]
        yield tuple(res)
>>>list(myzip('123', 'xyz'))
>>>[('1', 'x'), ('2', 'y'), ('3', 'z')]

 

注:转载《Learning Python 5th Edition》[奥莱理]

1. What is the difference between enclosing a list comprehension in square brackets and parentheses?
2. How are generators and iterators related?
3. How can you tell if a function is a generator function?
4. What does a yield statement do?
5. How are map calls and list comprehensions related? Compare and contrast the two.

1. List comprehensions in square brackets produce the result list all at once in memory. When they are enclosed in parentheses instead, they are actually  generator expressions—they have a similar meaning but do not produce the result list all at once. Instead, generator expressions return a generator object, which yields one item in the result at a time when used in an iteration context.
2. Generators are iterable objects that support the iteration protocol automatically—they have an iterator with a __next__ method (next in 2.X) that repeatedly advances to the next item in a series of results and raises an exception at the end of the series. In Python, we can code generator functions with def and yield, generator expressions with parenthesized comprehensions, and generator objects with classes that define a special method named __iter__ (discussed later in the book).
3. A generator function has a yield statement somewhere in its code. Generator functions are otherwise identical to normal functions syntactically, but they are compiled specially by Python so as to return an iterable generator object when called. That object retains state and code location between values.
4. When present, this statement makes Python compile the function specially as a generator; when called, the function returns a generator object that supports the iteration protocol. When the yield statement is run, it sends a result back to the caller and suspends the function’s state; the function can then be resumed after the last yield statement, in response to a next built-in or __next__ method call issued by the caller. In more advanced roles, the generator send method similarly resumes the generator, but can also pass a value that shows up as the yield expression’s value. Generator functions may also have a return statement, which terminates the generator.
5. The map call is similar to a list comprehension—both produce a series of values, by collecting the results of applying an operation to each item in a sequence or other iterable, one item at a time. The primary difference is that map applies a function call to each item, and list comprehensions apply arbitrary expressions. Because of this, list comprehensions are more general; they can apply a function call expression like map, but map requires a function to apply other kinds of expressions. List comprehensions also support extended syntax such as nested for loops and if clauses that subsume the filter built-in. In Python 3.X, map also differs in that it produces a generator of values; the list comprehension materializes the result list in memory all at once. In 2.X, both tools create result lists.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值