python之yield与装饰器


python中的yield:

  在之前发布的《python之列表解析与生成器》中我们有提到过,生成器所实现的是跟列表解析近似的效果,但是我们不能对生成器做一些属于列表解析的操作

  因为生成器本身就不是一个列表,它只是模拟了一个类似列表的行为,因此,施加在列表中的很多操作,对生成器而言是无效的。

  由于生成器表达式并不会直接创建出序列形式的列表,因此不能对其进行索引、切片,不能执行任何常规的列表操作。比如:弹出元素(pop())、添加元素(append())等等。但是我们可以通过list函数将生成器转换成列表。

1
2
In [ 1 ]:  list ((i * * 2  for  in  range ( 1 , 11 )))
Out[ 1 ]: [ 1 4 9 16 25 36 49 64 81 100 ]

  很多情况下我们需要生成更为复杂的结果,又不想基于某个列表来实现,但是简单的使用一个生成器表达式很难实现此种行为。此时我们可以通过一个自定义函数来完全实现类似的效果。  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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以内所有正整数的平方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
In [ 17 ]:  def  genNum(n):
     ...:     count  =  1
     ...:      while  count < =  n:
     ...:          yield  count  * *  2
     ...:         count  + =  1
     ...: 
 
In [ 18 ]: g1  =  genNum( 20 )
 
In [ 19 ]:  for  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.把一个函数名当做实参传给另一个函数(可以实现在不修改被装饰函数源代码的情况下为其添加功能)

1
2
3
4
5
6
7
8
9
10
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.返回值中包含函数名(可以实现不修改被装饰函数的调用方式)

1
2
3
4
5
6
7
8
9
import  time
def  bar():
     time.sleep( 3 )
     print ( 'in the bar' )
def  test2(func):
     print (func)
     return  func
=  test2(bar)     #此处也可以改成:bar = test2(bar)
bar()

  当用bar = test2(bar)时,此处定义的bar变量名就会覆盖之前定义bar函数时生成的变量名bar。

  如此的话,那之前定义的bar函数进行调用时就是使用新定义的bar变量名引用其在内存中的位置,从而达到不修改bar函数调用方式的目的。

    3、嵌套函数

1
2
3
4
5
6
7
import  time
def  foo():
     print ( 'in the foo' )
def  bar():
     print ( 'in the bar' )
bar()
foo()

  不带参数的func(被装饰的函数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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(被装饰的函数):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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...

  现在我们来写一个简单的为函数添加执行时间的装饰器函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import  time
def  timmer(func):
     def  wrapper( * args, * * kwargs):
         start_time  =  time.time()
         =  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个页面验证登录之后才能访问,另一个页面不用验证即可访问

  首先定义三个页面函数:

1
2
3
4
5
6
7
8
9
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'

  然后定义装饰器函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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()








本文转自 忘情OK  51CTO博客,原文链接:http://blog.51cto.com/itchentao/1885183,如需转载请自行联系原作者
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值