概述
## 生成器
#### 创建生成器
#### 方法一
~~~
In [15]: L = [ x*2 for x in range(5)]
In [16]: L
Out[16]: [0, 2, 4, 6, 8]
In [17]: G = ( x*2 for x in range(5))
In [18]: G
Out[18]: at 0x7f626c132db0>
注:其中L是一个列表 G是一个生成器,我们可以直接打印出L 的每一个元素。则 G可以通过next()函数获取生成器的下一个返回值,没有最后一个元素,则抛出异常。
In [19]: next(G)
Out[19]: 0
In [20]: next(G)
Out[20]: 2
In [21]: next(G)
Out[21]: 4
In [22]: next(G)
Out[22]: 6
In [23]: next(G)
Out[23]: 8
In [24]: next(G)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
in ()
----> 1 next(G)
StopIteration:
~~~
#### 方法二
带有 yield 的函数在 Python 中被称之为 generator(生成器)
生成斐波那契
~~~
#!/usr/bin/python
# -*- coding: UTF-8 -*-
def fab(max):
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n = n + 1
fab(5)
~~~
面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
~~~
In [30]: def fib(times):
....: n = 0
....: a,b = 0,1
....: while n
....: yield b // 用yield来声明为生成器函数
....: a,b = b,a+b
....: n+=1
....: return 'done'
....:
In [31]: F = fib(5) #创建一个生成器对象
In [32]: next(F)
Out[32]: 1
In [33]: next(F)
Out[33]: 1
In [34]: next(F)
Out[34]: 2
In [35]: next(F)
Out[35]: 3
In [36]: next(F)
Out[36]: 5
In [37]: next(F)
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
in ()
----> 1 next(F)
StopIteration: done
~~~
#### 其中next(F) 与F.__next()__方法一样
函数改成generator后,我们基本上从来不会用 next() 来获取下一个返回值,而是直接使用 for 循环来迭代:
~~~
In [38]: for n in fib(5):
....: print(n)
....:
1
1
2
3
5
In [39]:
~~~
但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
~~~
In [39]: g = fib(5)
In [40]: while True:
....: try:
....: x = next(g)
....: print("value:%d"%x)
....: except StopIteration as e:
....: print("生成器返回值:%s"%e.value)
....: break
....:
value:1
value:1
value:2
value:3
value:5
生成器返回值:done
In [41]:
~~~
2. ### [](https://note.youdao.com/md/?defaultMode=view&fileId=WEB67cf250cd280c428a4d3eca330bb66a6#send)send
例子:执行到yield时,gen函数作用暂时保存,返回i的值;temp接收下次c.send("python"),send发送过来的值,c.next()等价c.send(None)
~~~
In [43]: f = gen()
In [44]: f.__next__()
Out[44]: 0
In [45]: f.send('haha')
haha
Out[45]: 1
In [46]: f.__next__()
None
Out[46]: 2
In [47]: f.send('haha')
haha
Out[47]: 3
~~~
## 迭代器
代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
#### 判断是否可以跌代
~~~
In [50]: from collections import Iterable
In [51]: isinstance([], Iterable)
Out[51]: True
In [52]: isinstance({}, Iterable)
Out[52]: True
In [53]: isinstance('abc', Iterable)
Out[53]: True
In [54]: isinstance((x for x in range(10)), Iterable)
Out[54]: True
In [55]: isinstance(100, Iterable)
Out[55]: False
~~~
## iter()函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。
把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
~~~
In [62]: isinstance(iter([]), Iterator)
Out[62]: True
In [63]: isinstance(iter('abc'), Iterator)
Out[63]: True
~~~
## 闭包
~~~
#定义一个函数
def test(number):
#在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def test_in(number_in):
print("in test_in 函数, number_in is %d"%number_in)
return number+number_in
#其实这里返回的就是闭包的结果
return test_in
#给test函数赋值,这个20就是给参数number
ret = test(20)
#注意这里的100其实给参数number_in
print(ret(100))
#注意这里的200其实给参数number_in
print(ret(200))
运行结果:
in test_in 函数, number_in is 100
120
in test_in 函数, number_in is 200
220
~~~
### 闭包再理解
内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。
~~~
# closure.py
def counter(start=0):
count=[start]
def incr():
count[0] += 1
return count[0]
return incr
启动python解释器
>>>import closeure
>>>c1=closeure.counter(5)
>>>print(c1())
6
>>>print(c1())
7
>>>c2=closeure.counter(100)
>>>print(c2())
101
>>>print(c2())
102
nonlocal访问外部函数的局部变量(python3)
def counter(start=0):
def incr():
nonlocal start
start += 1
return start
return incr
c1 = counter(5)
print(c1())
print(c1())
c2 = counter(50)
print(c2())
print(c2())
print(c1())
print(c1())
print(c2())
print(c2())
~~~
#### 看一个闭包的实际例子:
~~~
def line_conf(a, b):
def line(x):
return a*x + b
return line
line1 = line_conf(1, 1)
line2 = line_conf(4, 5)
print(line1(5))
print(line2(5))
~~~
#### 装饰器
~~~
#定义函数:完成包裹数据
def makeBold(fn):
def wrapped():
return "" + fn() + ""
return wrapped
#定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
return "" + fn() + ""
return wrapped
@makeBold #当python解释器执行到这行代码的时候,那么就自动进行了装饰,而不是调用的时候才进行装饰
def test1():
return "hello world-1"
@makeItalic
def test2():
return "hello world-2"
@makeBold #test3 = makeBold(test3)
@makeItalic #test3 = makeItalic(test3)
def test3():
return "hello world-3"
print(test1()))
print(test2()))
print(test3()))
运行结果:
hello world-1
hello world-2
hello world-3
~~~
#### 装饰器(decorator)功能
1. 引入日志
2. 函数执行时间统计
3. 执行函数前预备处理
4. 执行函数后清理功能
5. 权限校验等场景
6. 缓存
### 装饰器示例
1. 无参数的函数
~~~
from time import ctime, sleep
def timefun(func):
def wrappedfunc():
print("%s called at %s"%(func.__name__, ctime()))
func()
return wrappedfunc
@timefun
def foo():
print("I am foo")
foo()
sleep(2)
foo()
~~~
上面代码理解装饰器执行行为可理解成 foo = timefun(foo) #foo先作为参数赋值给func后,foo接收指向timefun返回的wrappedfunc foo() #调用foo(),即等价调用wrappedfunc() #内部函数wrappedfunc被引用,所以外部函数的func变量(自由变量)并没有释放 #func里保存的是原foo函数对象
2. 被装饰的函数有参数
~~~
from time import ctime, sleep
def timefun(func):
def wrappedfunc(a, b):
print("%s called at %s"%(func.__name__, ctime()))
print(a, b)
func(a, b)
return wrappedfunc
@timefun
def foo(a, b):
print(a+b)
foo(3,5)
sleep(2)
foo(2,4)
~~~
3. 被装饰的函数有不定长参数
~~~
from time import ctime, sleep
def timefun(func):
def wrappedfunc(*args, **kwargs):
print("%s called at %s"%(func.__name__, ctime()))
func(*args, **kwargs)
return wrappedfunc
@timefun
def foo(a, b, c):
print(a+b+c)
foo(3,5,7)
sleep(2)
foo(2,4,9)
~~~
4. 装饰器中的return
~~~
from time import ctime, sleep
def timefun(func):
def wrappedfunc():
print("%s called at %s"%(func.__name__, ctime()))
func()
return wrappedfunc
@timefun
def foo():
print("I am foo")
@timefun
def getInfo():
return '----hahah---'
foo()
sleep(2)
foo()
print(getInfo())
~~~
5. 装饰器带参数,在原有装饰器的基础上,设置外部变量
~~~
from time import ctime, sleep
def timefun_arg(pre="hello"):
def timefun(func):
def wrappedfunc():
print("%s called at %s %s"%(func.__name__, ctime(), pre))
return func()
return wrappedfunc
return timefun
@timefun_arg("itcast")
def foo():
print("I am foo")
@timefun_arg("python")
def too():
print("I am too")
foo()
sleep(2)
foo()
too()
sleep(2)
too()
可以理解为
foo()==timefun_arg("itcast")(foo)()
~~~
注释 :通用装饰器的使用
~~~
# !usr/bin/python3
# -*-coding:utf8 -*-
# 通用装饰器
def func(functionName):
def func_in(*args,**kwargs):
return functionName(*args,**kwargs)
return func_in
# ① 不带返回值的装饰器
@func
def test1():
print('----test1----')
test1()
# ② 带返回值的装饰器
@func
def test2():
print("----test2------")
return "带装饰器的返回值"
ret = test2()
print(ret);
# ③ 带参数的装饰器
@func
def test3(a):
print("-----test3的参数值为%s"%a)
test3(11)
~~~
6. 类装饰器(扩展,非重点)
装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了**call**() 方法,那么这个对象就是callable的。
~~~
class Test():
def __call__(self):
print('call me!')
t = Test()
t() # call me
~~~
类装饰器demo
~~~
class Test(object):
def __init__(self, func):
print("---初始化---")
print("func name is %s"%func.__name__)
self.__func = func
def __call__(self):
print("---装饰器中的功能---")
self.__func()
#说明:
#1. 当用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
# 并且会把test这个函数名当做参数传递到__init__方法中
# 即在__init__方法中的func变量指向了test函数体
#
#2. test函数相当于指向了用Test创建出来的实例对象
#
#3. 当在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法
#
#4. 为了能够在__call__方法中调用原来test指向的函数体,所以在__init__方法中就需要一个实例属性来保存这个函数体的引用
# 所以才有了self.__func = func这句代码,从而在调用__call__方法中能够调用到test之前的函数体
@Test
def test():
print("----test---")
test()
showpy()#如果把这句话注释,重新运行程序,依然会看到"--初始化--"
~~~
最后
以上就是多情小海豚为你收集整理的python内置的生成器_python 生成器的全部内容,希望文章能够帮你解决python内置的生成器_python 生成器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复