装饰器

函数对象

 1 #函数是第一类对象:指的是函数可以当做数据传递#函数如果不加()就是引用这个函数,加上()输出返回值,
 2 #1、可以被引用 x=1,y=x
 3 # def func(x,y):
 4 #     print(x,y)
 5 #
 6 # f=func
 7 # f(1,2)
 8 #2、可当做函数的参数传入
 9 # def foo():
10 #     print('from foo')
11 #
12 # def bar(func):
13 #     # print(func)
14 #     func()#这里指的是拿到函数foo的内存地址了加()就能调用
15 #
16 # bar(foo)
17 
18 #3、可以当做函数的返回值
19 # def foo():
20 #     print('from foo')
21 #
22 # def bar():
23 #     return foo
24 #
25 # f=bar()#有返回值,要保存就定义个变量
26 # f()#拿到函数foo的内存地址了加()就能调用
27 
28 #4、可以当做容器类型的元素
29 # def foo():
30 #     print('from foo')
31 #
32 # def bar():
33 #     return foo
34 #
35 # l=[foo,bar]
36 # print(l)
37 # l[0]()
38 
39 
40 # def get():
41 #     print('get')
42 #
43 # def put():
44 #     print('put')
45 #
46 # def ls():
47 #     print('ls')
48 #
49 # cmd=input('>>: ').strip()
50 # if cmd == 'get':
51 #     get()
52 # elif cmd == 'put':
53 #     put()
54 # elif cmd == 'ls':
55 #     ls()
56 
57 
58 
59 
60 def get():
61     print('get')
62 
63 def put():
64     print('put')
65 
66 def ls():
67     print('ls')
68 
69 def auth():
70     print('auth')
71 
72 func_dic={
73     'get':get,
74     'put':put,
75     'ls':ls,
76     'auth':auth
77 }
78 
79 # func_dic['put']()
80 cmd = input('>>: ').strip()
81 if cmd in func_dic:
82     func_dic[cmd]()

 函数嵌套

 1 #1、函数的嵌套调用
 2 # def my_max(x,y):
 3 #     if x >= y:
 4 #         return x
 5 #     else:
 6 #         return y
 7 #
 8 # def my_max4(a,b,c,d):
 9 #     res1=my_max(a,b)
10 #     res2=my_max(res1,c)
11 #     res3=my_max(res2,d)
12 #     return res3
13 
14 
15 #2、函数的嵌套定义
16 def f1():
17     def f2():
18         print('from f2')
19         def f3():
20             print('from f3')
21         f3()
22     # print(f2)
23     f2()
24 
25 
26 f1()
27 # f2#在函数内部定义的函数只能在内部用(在当前级别定义的函数只能在当前级别使用)

名称空间

  1 #名称空间指的是:存放名字与值绑定关系的地方,
  2 
  3 #内置名称空间(python解释器启动就有):python解释器内置的名字,max,len,print
  4 #全局名称空间(执行python文件时生效):文件级别定义的名字(定头写),不是内置的也不是函数内部定义的
  5 # 1.x=1
  6 # 2.def func():pass
  7 # 3.import time
  8 # 4.if x == 1:
  9 #     y=2
 10 
 11 #局部名称空间(函数调用时生效,调用结束失效):函数内部定义的名字,
 12 # func()
 13 
 14 #加载顺序:内置---》全局----》局部名称空间
 15 #访问名字的顺序:局部名称空间===》全局----》内置
 16 # x=1
 17 # print(x)
 18 
 19 # print(max)
 20 
 21 # max=2
 22 # def func():
 23 #     # max=1#把它注释掉就是不从局部找,就要从全局找,全局找到max=2,就会把值给func()
 24 #     print(max)
 25 #
 26 # func()
 27 
 28 
 29 # x='gobal'
 30 # def f1():
 31 #     # x=1
 32 #     def f2():
 33 #        # x=2
 34 #        def f3():
 35 #            # x=3
 36 #            print(x)
 37 #        f3()
 38 #     f2()
 39 #
 40 # f1()
 41 
 42 
 43 
 44 #全局作用域(全局范围):内置名称空间与全局名称空间的名字,全局存活,全局有效,globals()#查看全局作用于的名
 45 #局部作用域(局部范围):局部名称空间的名字,临时存活,局部有效,locals()#查看局部作用于的名
 46 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=111111111111111111111
 47 # print(globals())
 48 # print(dir(globals()['__builtins__']))#先不用考虑
 49 
 50 # print(locals() is globals())#结果是True
 51 
 52 # def func():
 53 #     yyyyyyyyyyyyyyyyyyyyyyyy=22222222
 54 #     print(globals())
 55 #     print(locals())
 56 #
 57 # func()
 58 
 59 
 60 # x=100
 61 # def func():
 62 #     global x#加上这个指的这个x是全局的名字,print(x)为100,不加这个指的是局部的名字,所以print(x)为100
 63 #     x=1
 64 #
 65 # func()
 66 # print(x)
 67 
 68 
 69 
 70 # x='global'
 71 # def f1():
 72 #     # x=1
 73 #     def f2():
 74 #         nonlocal x#改当前层函数的外面一层
 75 #         x=0
 76 #     f2()
 77 #     print('===f1 innter--->',x)
 78 #
 79 # f1()
 80 # print(x)
 81 
 82 
 83 
 84 
 85 
 86 #强调两点:
 87 #1、打破函数层级限制来调用函数
 88 # def outter():
 89 #     def inner():
 90 #         print('inner')
 91 #     return inner#上面函数中定义完了的函数可以做返回值来调用
 92 #
 93 # f=outter()
 94 # # print(f)
 95 #
 96 # def bar():
 97 #     f()
 98 # bar()
 99 
100 
101 #2、函数的作用域关系是在函数定义阶段就已经固定了,与调用位置无关
102 x=1
103 def outter():
104     # x=2
105     def inner():
106         print('inner',x)
107     return inner
108 
109 f=outter()
110 # print(f)
111 # x=1111111111111111111111111111111111111111111111111111111111111111111111111111111111#把值放到这个地方,指的是在下面f()再调用的时候全局名称空间的值已经变成这个值了
112 def bar():
113     x=3
114     f()
115 # x=1111111111111111111111111111111111111111111111111111111111111111111111111111111111#这依然是在全局的
116 bar()
117 x=1111111111111111111111111111111111111111111111111111111111111111111111111111111111#上面已经执行完所以值不会变
118 
119 
120 def outter():
121     def inner():
122         print('inner')
123 
124     return inner
125 f=outter()
126 print(f)
127 
128 def bar():
129     f()
130 bar()#bar调用的是f这个名称空间的值

闭包函数

 1 #闭包函数:
 2 #1 定义在函数内部的函数
 3 #2 该函数的函数体代码包含对外部作用域(而不是全局作用域)名字的引用
 4 #3 通常将闭包函数用return返回,然后可以在任意使用
 5 #def outer():
 6 #    x=1
 7 #    def inner():#这个函数就叫闭包函数
 8 #        print(x)#这个函数体要引用x这个名字,而这个名字在上一级的函数体中就叫闭包函数
 9 #
10 #
11 # z=1
12 # def outer():
13 #     x=1
14 #     y=2
15 #     def inner():
16 #         print(x,y)
17 #         # print(z)
18 #     return inner#定义在函数内部的函数受层级的限制,只能当前位置使用,要想打破层级限制,就要return
19 #
20 # f=outer()
21 # print(f.__closure__[0].cell_contents)#显示闭包函数的值
22 # print(f.__closure__[1].cell_contents)
23 # print(f.__closure__)
24 
25 
26 # def bar():
27 #     x=111121
28 #     y=2222
29 #     f()#f可以在这调用
30 #
31 # bar()
32 
33 
34 
35 两种给函数传参
36     (1)通过参数传给他
37 # def foo(x,y):
38 #     print(x+y)
39 #
40 # foo(1,2)
41     (2)把参数的值报给他(闭包函数)
42 # def outter():
43 #     x=1
44 #     y=2
45 #     def foo():
46 #         print(x+y)
47 #     return foo
48 #
49 #
50 # f=outter()
51 #
52 # f()
53 
54 
55 
56 #爬页面:闭包函数为我们提供了一种新的为函数传参的方式
57 import requests #pip3 install requests
58 
59 # def get(url):
60 #     response=requests.get(url)
61 #     if response.status_code == 200:
62 #         print(len(response.text))
63 #
64 # get('https://www.baidu.com')
65 # get('https://www.baidu.com')
66 # get('https://www.baidu.com')
67 
68 def outter(url):
69     # url = 'https://www.baidu.com'
70     def get():
71         response=requests.get(url)
72         if response.status_code == 200:
73             print(len(response.text))
74     return get
75 
76 baidu=outter('https://www.baidu.com')
77 python=outter('https://www.python.org')
78 # baidu()
79 # baidu()
80 # baidu()

装饰器

 1 #1、开放封闭原则:对扩展开放,对修改是封闭
 2 
 3 #2、装饰器:装饰它人的,器指的是任意可调用对象,现在的场景装饰器-》函数,被装饰的对象也是-》函数
 4 #原则:1、不修改被装饰对象的源代码 2、不修改被装饰对象的调用方式
 5 #装饰器的目的:在遵循1,2的前提下为被装饰对象添加上新功能
 6 
 7 #错误的示范
 8 # import time
 9 #
10 # def index():
11 #     time.sleep(3)
12 #     print('welecome to index')
13 #
14 # def timmer(func):#函数体代码需要参数相当于func=某个值
15 #     start=time.time()
16 #     func()
17 #     stop=time.time()
18 #     print('run time is %s' %(stop-start))
19 #
20 # timmer(index)
21 
22 
23 
24 import time
25 def index():
26     time.sleep(3)
27     print('welecome to index')
28 
29 def timmer(func):
30     # func=index #最原始的index#这个值是要个inner下面的
31     def inner():
32         start=time.time()
33         func() #最原始的index
34         stop=time.time()
35         print('run time is %s' %(stop-start))
36     return inner
37 
38 index=timmer(index) #index=inner
39 # print(f)
40 index() #inner()

加上段点就是要走import time,def index,def timmer,index=timmer(index),从这几个走的,当走到index=timmer(index)的时候
就会调用timmer这个函数,就会把最初的index传给func了,就会到def inner,这就到index=timmer(index),括号中的index就是inner
的值
 1 #装饰器语法:在被装饰对象正上方单独一行写上,@装饰器名
 2 
 3 # #改进一:
 4 # import time
 5 # def timmer(func):
 6 #     def inner():
 7 #         start=time.time()
 8 #         res=func()
 9 #         stop=time.time()
10 #         print('run time is %s' %(stop-start))
11 #         return res
12 #     return inner
13 #
14 # @timmer #index=timmer(index)#这个@符号指的是把@timmer正下方的函数名当作参数传给timmer这个函数(timmer(index)),并且把这个结果重新命名给index
15 # def index():
16 #     time.sleep(1)
17 #     print('welecome to index')
18 #     return 1111#如果有返回值,
19 #
20 # res=index() #res=inner()
21 # print(res)
22 
23 
24 #改进二:*args **kwargs
25 import time
26 def timmer(func):
27     def inner(*args,**kwargs):
28         start=time.time()
29         res=func(*args,**kwargs)
30         stop=time.time()
31         print('run time is %s' %(stop-start))
32         return res
33     return inner
34 
35 # @timmer #index=timmer(index)
36 # def index(name):
37 #     time.sleep(1)
38 #     print('welecome %s to index' %name)
39 #     return 1111
40 # res=index('egon') #res=inner('egon')
41 # print(res)
42 
43 
44 
45 import time
46 def timmer(func):
47     def inner(*args,**kwargs):
48         start=time.time()
49         res=func(*args,**kwargs)
50         stop=time.time()
51         print('run time is %s' %(stop-start))
52         return res
53     return inner
54 @timmer #home=timmer(home)
55 def home(name):
56     print('welcome %s to home page' %name)
57 
58 home('egon') #inner('egon')

 有参装饰器

 1 import time
 2 def auth(engine='file'):
 3     def outter(func):
 4         def inner(*args,**kwargs):   #这里接受任意
 5             if engine == 'file':
 6                 name=input('name>>>').strip()
 7                 passwd=input('passwd>>>').strip()
 8                 if name == 'lqx' and passwd == '123':
 9                     print('login seccussfull')
10                     res=func(*args,**kwargs)   #那么这里也应该有参数
11                     return res
12                 else:
13                     print('login err')
14             elif engine == 'mysql':
15                 print('login')
16             else:
17                 print('login err')
18         return inner
19     return outter
20 # engine='file'
21 @auth(engine='file')  #outter #index=auth(index)
22 #@outter
23 def index(name,*args,**kwargs):  #如果这里有参数
24     time.sleep(0.5)
25     print('welecome to index %s'%name)
26     return 11112312312312312
27 a=index('lqx',18,231312)   #如果这里有参数,那么上面的inner也应该有接受参数的形参
28 print(a)

并行多个装饰器

这里的意思的用俩个装饰器,第一个装饰器修饰第二个装饰器,第二个装饰器修饰下面的原函数。因此,这里的第一个装饰器一定是一个可以完全修饰任意原函数的一个装饰器

  

 1 import time
 2 
 3 def timmer(func):
 4     def inner(*args,**kwargs):
 5         start=time.time()
 6         res=func(*args,**kwargs)
 7         stop=time.time()
 8         print(stop - start)
 9         return res
10     return inner
11 def auth2(engine='file'):
12     def auth(func):
13         def inner(*reags,**kwargs):
14             if engine == 'file':
15                 name=input('name>>>').strip()
16                 passwd=input('passwd>>>').strip()
17                 if name == 'lqx' and passwd == '123':
18                     print('login successfull')
19                     res=func(*reags,**kwargs)
20                     return res
21                 else:
22                     print('login err')
23             elif engine == 'mysql':
24                 print('mysql auth')
25             else:
26                 print('login err')
27         return inner
28     return auth
29 @timmer
30 @auth2(engine='file')
31 def index(name,*args):
32     time.sleep(1)
33     print('welecome %s to index'%name)
34     return 12341234123123123123123131231232132131231231
35 
36 a=index('lqx',123,'age','sex')
37 print(a)

warps注释信息伪装

1 使用模块wraps,实际上这个wraps也是一个装饰器, 
2 只要把@wraps,放到原函数的传值的上面就可以实现 
3 然后在原函数的后面执行print(help(原函数)),就可以看到原函数的注释信息
 1 from functools import wraps    #注释信息伪装
 2 import time
 3 def timmer(func):
 4     @wraps(func)   #注释信息模块
 5     def inner(*args,**kwargs):
 6         start=time.time()
 7         res=func(*args,**kwargs)
 8         stop=time.time()
 9         print(stop - start)
10         return res
11     # inner.__doc__ = func.__doc__  # 把index的注释信息赋值给inner
12     # inner.__name__=func.__name__   #把index的注释新的的名字也赋值给inner
13     return inner
14 @timmer
15 def index(name):
16     '''index 函数。。。。。'''
17     time.sleep(1)
18     print('welecome %s to index'%name)
19     return 12341234123123123123123131231232132131231231
20 print(help(index))
原文地址:https://www.cnblogs.com/yinfutao/p/8059669.html