发布时间:2019-09-18 07:27:56编辑:auto阅读(1700)
防伪码:忘情公子著
python中的yield:
在之前发布的《python之列表解析与生成器》中我们有提到过,生成器所实现的是跟列表解析近似的效果,但是我们不能对生成器做一些属于列表解析的操作。
因为生成器本身就不是一个列表,它只是模拟了一个类似列表的行为,因此,施加在列表中的很多操作,对生成器而言是无效的。
由于生成器表达式并不会直接创建出序列形式的列表,因此不能对其进行索引、切片,不能执行任何常规的列表操作。比如:弹出元素(pop())、添加元素(append())等等。但是我们可以通过list函数将生成器转换成列表。
In [1]: list((i**2 for i in range(1,11))) Out[1]: [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
很多情况下我们需要生成更为复杂的结果,又不想基于某个列表来实现,但是简单的使用一个生成器表达式很难实现此种行为。此时我们可以通过一个自定义函数来完全实现类似的效果。
In [2]: def genNum(x): ...: y = 0 ...: while y <= x: ...: yield y ...: y += 1 ...: In [3]: g1 = genNum(10) In [4]: type(g1) Out[4]: generator In [5]: g1.next() Out[5]: 0 In [6]: g1.next() Out[6]: 1 In [7]: g1.next() Out[7]: 2 In [8]: g1.next() Out[8]: 3 In [9]: g1.next() Out[9]: 4 In [10]: g1.next() Out[10]: 5 In [11]: g1.next() Out[11]: 6 In [12]: g1.next() Out[12]: 7 In [13]: g1.next() Out[13]: 8 In [14]: g1.next() Out[14]: 9 In [15]: g1.next() Out[15]: 10 In [16]: g1.next() --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-16-9066a8f18086> in <module>() ----> 1 g1.next() StopIteration:
yield本身并不是一个返回值,却能够生成一个生成器对象。
yield保存着一个对象的状态信息。(快照的例子:快照当中保存的是执行快照时的状态)
如上例所看到的,当我们在函数中使用yield,会返回一个生成器对象。
求1到20以内所有正整数的平方:
In [17]: def genNum(n): ...: count = 1 ...: while count <= n: ...: yield count ** 2 ...: count += 1 ...: In [18]: g1 = genNum(20) In [19]: for i in g1: ...: print i ...: 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400
Python中的装饰器:
装饰器定义:
本质上是一个函数
功能是用来装饰其他函数。就是为其他函数添加附加功能
装饰器=高阶函数+嵌套函数
装饰器特定的原则:
不能修改被装饰的函数的源代码(线上环境)
不能修改被装饰的函数的调用方式
不能修改被装饰的函数的返回值
装饰器可以抽离出大量的函数中与函数无关的功能,把函数本身只作为一个核心,在必要时如果函数的核心功能不够,就用装饰器装饰一下本次调用所需要的功能,于是运行结束了,下次当需要其它功能时再用装饰器给重新装饰一下就可以了,这就是装饰器。
装饰器需要接受一个函数对象作为其参数,而后对此函数做包装,以对此函数进行增强。
实现装饰器的知识储备:
1、函数即“变量“(说明变量在内存中存在的方式)
2、高阶函数
a.把一个函数名当做实参传给另一个函数(可以实现在不修改被装饰函数源代码的情况下为其添加功能)
import time def bar(): time.sleep(3) print('in the bar') def test1(func): start_time = time.time() func() stop_time = time.time() print('The func run time is %s'% (stop_time-start_time)) test1(bar)
b.返回值中包含函数名(可以实现不修改被装饰函数的调用方式)
import time def bar(): time.sleep(3) print('in the bar') def test2(func): print(func) return func x = test2(bar) #此处也可以改成:bar = test2(bar) bar()
当用bar = test2(bar)时,此处定义的bar变量名就会覆盖之前定义bar函数时生成的变量名bar。
如此的话,那之前定义的bar函数进行调用时就是使用新定义的bar变量名引用其在内存中的位置,从而达到不修改bar函数调用方式的目的。
3、嵌套函数
import time def foo(): print('in the foo') def bar(): print('in the bar') bar() foo()
不带参数的func(被装饰的函数):
In [20]: def decorative(func): ...: def wrapper(): #定义一个包装器 ...: print "Please say something: " ...: func() #调用func,这个func是我们自己定义的 ...: print "No zuo no die..." ...: return wrapper ...: In [21]: @decorative #使用@符号调用装饰器 ...: def show(): #定义func,名字取什么都无所谓,它只是用来传给装饰器中的func参数 ...: print "I'm from Mars." ...: show() ...: Please say something: I'm from Mars. No zuo no die...
如上例所示,show函数本身只有一个print语句,而使用装饰器以后,就变成了三个print,这里的print可以改成任何其它的语句,这就是函数的装饰器。
带参数的func(被装饰的函数):
In [22]: def decorative(func): ...: def wrapper(x): ...: print "Please say something...>" ...: func(x) ...: print "no zuo no die..." ...: return wrapper ...: In [23]: @decorative ...: def show(x): ...: print x ...: In [24]: show("hello,mars.") Please say something...> hello,mars. no zuo no die...
现在我们来写一个简单的为函数添加执行时间的装饰器函数:
import time def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() a = func() stop_time = time.time() print('The func run time is %s'% (stop_time-start_time)) return a return wrapper @timmer def foo(): time.sleep(3) print('in the foo') print(foo())
接下来再写一个现实生活中能用得到的:
需求如下:
假定有三个页面,现在要实现其中2个页面验证登录之后才能访问,另一个页面不用验证即可访问
首先定义三个页面函数:
def index(): print('Welcome to index page') return 'from index page' def home(): print('Welcome to home page') return 'from home page' def bbs(): print('Welcome to bbs page') return 'from bbs page'
然后定义装饰器函数:
user = sean passwd = abc123 def auth(auth_type='local'): def out_wrapper(func): def wrapper(*args,**kwargs): if auth_type == 'local': username == input('Username: ').strip() password == input('Password: ').strip() if user == username and passwd == password: print('authentication passed') func() elif auth_type == 'ldap': print('This is ldap authentication') func() return wrapper return out_wrapper
接下来将装饰器分别应用于home函数与bbs函数:
def index(): print('Welcome to index page') return 'from index page' @auth(auth_type='local') def home(): print('Welcome to home page') return 'from home page' @auth(auth_type='ldap') def bbs(): print('Welcome to bbs page') return 'from bbs page' #调用函数 index() home() bbs()
上一篇: SAP的产品为什么叫R3?
下一篇: python测试应用级别
47840
46386
37279
34731
29312
25970
24909
19949
19541
18026
5790°
6411°
5926°
5960°
7063°
5910°
5942°
6437°
6404°
7776°