闭包
- 嵌套函数
# 定义一个外层函数
def foo():
# 定义了一个内部函数
def bar():
print("hello world")
bar()
- 函数
bar
是一个定义在foo
函数内部的函数。Python中的函数是支持嵌套的,也就是可以在一个函数内部再定义一个函数。然后,我们还知道函数是可以当作变量的,于是我们就可以在foo
函数中把定义的这个bar
函数返回。就像下面这样:
# 定义一个外层函数
def foo():
# 定义了一个内层函数
def bar():
print("hello world")
return bar
func = foo()
func() # func --> bar,这里执行func其实就相当于执行了在foo函数内部定义的bar函数
- 闭包
def foo():
name = "Andy" # 外部函数的局部变量,同样也可以作为参数传入
# 定义了一个内部函数
def bar():
print(name) # 虽然bar函数中没有定义name变量,但是它可以访问外部函数的局部变量name
return bar
func = foo()
func() # func --> bar --> 除了是一个函数,还包含一个值(它外层函数的局部变量)的引用
装饰器
- 装饰器通常是一个命名的对象(不允许使用 lambda 表达式),在被装饰函数调用时接受单一参数,并返回另一个可调用对象。
- 事实上,任何函数都可以用作装饰器,因为Python并没有规定装饰器的返回类型。
示例:
import time
import random
# 注意返回的是内部函数不是传入的参数
def f1(func):
def f2():
t1 = time.time()
func()
t2 = time.time()
print('用时 %s 秒' % (t2-t1))
return f2
@f1
def f():
t = random.random()
time.sleep(t)
print('t = %s' % t)
# f()
"""
等价于
x = f1(f)
x()
"""
迭代器
- 迭代器(Iterators)的使用非常普遍并使得 Python 成为一个统一的整体。 在幕后,
for
语句会调用容器对象中的iter()
。 该函数返回一个定义了__next__()
方法的迭代器对象,该方法将逐一访问容器中的元素。 当元素用尽时,__next__()
将引发StopIteration
异常来通知终止for
循环。 你可以使用next()
内置函数来调用__next__()
方法;这个例子显示了它的运作方式:
示例:
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> next(it)
'a'
>>> next(it)
'b'
>>> next(it)
'c'
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
next(it)
StopIteration
生成器
- 生成器 Generator 是一个用于创建迭代器的简单而强大的工具。 它们的写法类似标准的函数,但当它们要返回数据时会使用
yield
语句。 每次对生成器调用next()
时,它会从上次离开位置恢复执行(它会记住上次执行语句时的所有数据值)。 显示如何非常容易地创建生成器的示例如下:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
... print(char)
...
f
l
o
g
生成器表达式
- 某些简单的生成器可以写成简洁的表达式代码,所用语法类似列表推导式,将外层为圆括号而非方括号。 这种表达式被设计用于生成器将立即被外层函数所使用的情况。 生成器表达式相比完整的生成器更紧凑但较不灵活,相比等效的列表推导式则更为节省内存。
例如:
>>> sum(i*i for i in range(10)) # sum of squares
285
>>> xvec = [10, 20, 30]
>>> yvec = [7, 5, 3]
>>> sum(x*y for x,y in zip(xvec, yvec)) # dot product
260
- 总结