Day4-装饰器

装饰器,本质是函数,为其它函数添加附加功能。

装饰器对被装饰的函数没有任何影响,原则:

1.不能修改被装饰的函数的源代码;2.不能修改调用方式;

高阶函数+嵌套函数,实现装饰器,准备知识如下:

1.函数和变量的区别:

变量存在内存中,比如x=1 ,1存在内存中,x就是内存的门牌号。若y=x,y也是一次引用,即y也是门牌号,清除变量1的话必须清除x和y。
def test(): #定义了test函数,即函数体存在内存中,test为门牌号
      pass
test = ‘函数体 ‘

python的内存回收器由python解释器回收的,清除变量通过清除所有门牌号的方式清除。

lambda匿名函数:没有起名,正是因为没有名字,它就没有门牌号,立马被python解释器回收掉
calc=lambdax:x*3
print(calc(3))
9

总结:函数就是变量,定义一个函数,等于把函数体给了函数名。变量有内存回收机制,函数一样。
先声明再调用,只要在调用之前声明就可以正常执行。因为声明是定义函数名,把函数体存在内存中。

2.高阶函数,满足的条件:

a.把一个函数名当做实参传给另外一个函数;(不修改被装饰函数源代码的情况下为其添加功能)
b.返回值中包含函数名(不修改函数的调用方式)

 1 import time
 2 def bar():
 3     time.sleep(3)
 4     print("in the bar")
 5
 6 def test1(func):
 7     start_time = time.time()
 8     func()
 9     stop_time=time.time()
10     print("in the func run time is %s" %(start_time-stop_time))
11
12 test1(bar)
13 结果:
14 in the bar
15 in the func run time is -3.014805555343628

3.嵌套函数:在def函数体内再def声明一个函数,叫嵌套函数

 1 #函数的调用
 2 def test1():
 3     test2()  #函数的调用,不叫嵌套
 4 test1()
 5
 6 #嵌套函数
 7 def foo():
 8     print("in the foo")
 9     def bar():
10         print("in the bar")
11     bar() #局部变量必须在函数内部调用
12 foo()
13 #bar()  #这引用是不对的

4.装饰器的形成步骤

a.改变函数调用方式:正常为test1(),变为deco(test1)

需求:计算test1和test2函数运行时间

 1 import time
 2 def deco(func):
 3     start_time = time.time()
 4     func()
 5     stop_time = time.time()
 6     print("the func run time is %s" %(start_time-stop_time))
 7 def test1():
 8     time.sleep(3)
 9     print("in the test1")
10 def test2():
11     time.sleep(3)
12     print("in the test2")
13 deco(test1) #test1代表函数/变量,而test1()表示返回test1的运行结果
14 deco(test2)
15 执行结果:
16 in the test1
17 the func run time is -3.010805130004883
18 in the test2
19 the func run time is -3.012805461883545

分析:改变了函数的调用方式,违反原则。

b.返回值调用方式:func(),变成return func

 1 import time
 2 def deco(func):
 3     start_time = time.time()
 4     return func #返回执行结果,下面语句就不执行了
 5     stop_time = time.time()
 6     print("the func run time is %s" %(start_time-stop_time))
 7 def test1():
 8     time.sleep(3)
 9     print("in the test1")
10 def test2():
11     time.sleep(3)
12     print("in the test2")
13 test1 = deco(test1)
14 test1()
15 test2 = deco(test2)
16 test2()
17
18 执行结果:
19 in the test1
20 in the test2

分析:返回值调用不修改源代码和调用方式,但需求未实现。

c.加了嵌套函数:函数中定义新函数,返回新函数的变量名=内存地址=函数名,把返回值赋予一个变量,执行变量即可得到结果

 1 import time
 2 def timer(func):#func=test1,把test1函数作为timer函数的参数传递进去
 3     def deco(): #函数timer中定义新函数deco,即为函数嵌套
 4         start_time = time.time()
 5         func() #func=test1,运行func(),即为运行test1()
 6         stop_time = time.time()
 7         print("the func run time is %s"%(start_time-stop_time))
 8     return deco #返回deco内存地址,即为高级函数
 9 def test1():
10     time.sleep(3)
11     print("in the test1")
12 test2 = timer(test1) #把test1()函数的内存地址test1作为参数传递给timer函数
13 test2() #执行test2()函数
14
15 执行结果:
16 in the test1
17 the func run time is -3.010805130004883

d.装饰器

 1 import time
 2 def timer(func):
 3     def deco():
 4         start_time = time.time()
 5         func()
 6         stop_time = time.time()
 7         print("the fun run time is %s"%(start_time-stop_time))
 8     return deco
 9
10 @timer #给test1增加新功能
11 def test1():
12     time.sleep(3)
13     print("in the test1")
14
15 test1() #执行deco函数时,嵌套执行的是func()函数,即test1()=func()
16
17 执行结果:
18 in the test1
19 the fun run time is -3.0118050575256348

若被修饰的函数test1带位置参数,会咋样?

 1 @timer
 2 def test2(name):
 3     time.sleep(2)
 4     print("in the test2",name)
 5 test2()
 6
 7 执行结果:报错
 8 TypeError: test2() missing 1 required positional argument: ‘name‘
 9 分析:
10 test2()相当于函数timer()中的func()函数,在嵌套函数deco()中执行时func()没有位置参数name,所以报错。

e.装饰器:举例说明带可变参数和不带参数

 1 import time
 2 def timer(func):
 3     def deco(*args,**kwargs):
 4         start_time = time.time()
 5         func(*args,**kwargs)
 6         stop_time = time.time()
 7         print("the fun run time is %s"%(stop_time-start_time))
 8     return deco
 9
10 @timer
11 def test1():
12     time.sleep(2)
13     print("in the test1")
14 @timer
15 def test2(name,age):
16     time.sleep(2)
17     print("in the test2",name,age)
18
19 test1()
20 test2(‘alex‘,22)
21
22 执行结果:
23 in the test1
24 the fun run time is 2.0124034881591797
25 in the test2 alex 22
26 the fun run time is 2.0124034881591797

总结:装饰器又叫语法糖。

用途:公司有网站很多页面,一个页面一个函数,现在100个页面里有20个页面需要登录才能看到,所以在20个页面函数里加上验证功能才能看到。

需求1:编写一个登陆认证程序,主页index不需要登录,用户自己的home和bbs需要登录

 1 #!/usr/bin/env python
 2 import time
 3 user,passwd = ‘alex‘,‘abc123‘
 4 def auth(func):
 5     def wrapper(*args,**kwargs):
 6         username = input("Username:").strip()
 7         password = input("Password:").strip()
 8
 9         if user == username and passwd == password:
10             print("\033[32:1mGreat,user got it!\033[0m")
11             return func(*args,**kwargs)
12         else:
13             exit("\033[31:1mInvalid username or password\033[0m")
14             #exit()
15     return wrapper
16
17 def index():
18     print("Welcome to index page.")
19
20 @auth
21 def home():
22     print("Great,home page got it!")
23     return "from home"
24
25 @auth
26 def bbs():
27     print("Great,bbs page got it!")
28
29 index()
30 home()
31 bbs()
32
33 执行结果:
34 Welcome to index page.
35 Username:alex #执行home()需要输入用户名和密码
36 Password:abc123
37 [32:1mGreat,user got it![0m
38 Great,home page got it!
39 Username:alex  #执行bbs时需要再次输入用户名和密码
40 Password:abc123
41 [32:1mGreat,user got it![0m
42 Great,bbs page got it!

需求2,终极版:home实现本地认证,bbs实现ldap认证

 1 import time
 2 user,passwd = ‘alex‘,‘abc123‘
 3 def auth(auth_type):
 4     print("auth func:",auth_type)
 5     def out_wrapper(func):
 6         def wrapper(*args,**kwargs):
 7             print("wrapper func:",*args,**kwargs)
 8             if auth_type == "local":
 9                 username = input("Username:").strip()
10                 password = input("Password:").strip()
11
12                 if user == username and passwd == password:
13                     print("\033[32:1mGreat user got it!\033[0m")
14                     return func(*args,**kwargs)
15                 else:
16                     exit("\033[31:1mInvaild username or password\033[0m")
17             elif auth_type == "ldap":
18                 print("搞毛线ldap,不会")
19         return wrapper
20     return out_wrapper
21
22 def index():
23     print("Welcome to index page.")
24
25 @auth(auth_type="local")#这句话相当于home() = wrapper(),接下来home才开始执行
26 def home():
27     print("Welcome to home page.")
28     return "From home"
29
30 @auth(auth_type="ldap")
31 def bbs():
32     print("Welcome to bbs page.")
33
34 index()
35 home()
36 bbs()
37
38 执行结果:
39 auth func: local
40 auth func: ldap
41 Welcome to index page.
42 wrapper func:
43 Username:alex
44 Password:abc123
45 [32:1mGreat user got it![0m
46 Welcome to home page.
47 wrapper func:
48 搞毛线ldap,不会

时间: 2024-10-12 08:20:42

Day4-装饰器的相关文章

day4装饰器

Python装饰器 1.必备 def foo(): print(foo) <function foo at 0x7f62db093f28> >>> foo <function foo at 0x7f62db093f28> foo是函数,函数体: foo()是执行foo函数 def foo(): print(foo) foo = lambda x:x+1 foo()将执行lambda表达式,而不再是原来的foo函数,这是因为函数foo被重新定义了. 2.需求来了 初

day4装饰器-迭代器&amp;&amp;生成器

一.装饰器 定义:本质是函数,(装饰其他函数)就是为其它函数添加附加功能 原则:1.不能修改被装饰的函数的源代码 2.不能修改被装饰的函数的调用方式 实现装饰器知识储备: 1.函数及“变量” 2.高阶函数 a.把一个函数名当做实参传给另一个函数(在不修改被装饰器函数源代码的情况下为其添加新功能) b.返回值中包含函数名 3.嵌套函数 高阶函数+嵌套函数 = 装饰器 延迟3秒 import time def test1(): time.sleep(3) print('in the test1')

Day4 装饰器——迭代器——生成器

一 装饰器 1.1 函数对象 一 函数是第一类对象,即函数可以当作数据传递 #1 可以被引用 #2 可以当作参数传递 #3 返回值可以是函数 #3 可以当作容器类型的元素 二 利用该特性,优雅的取代多分支的if def foo(): print('foo') def bar(): print('bar') dic={ 'foo':foo, 'bar':bar, } while True: choice=input('>>: ').strip() if choice in dic: dic[ch

装饰器前奏

一.定义 1.装饰器:本质是函数. 2.功能:用来装饰其他函数,顾名思义就是,为其他的函数添加附件功能的. 二.原则 1.不能修改被装饰函数的源代码 2.不能修改被装饰函数的调用方式 装饰器为什么会有这两个原则呐?因为如果你写的这个程序在生产环境下已经运行了,如果修改别人的源代码或者修改别人的调用方式,那么出了问题,后果可想而知,所以我们要牢记上面两个原则. 三.实现装饰器知识储备 函数即"变量" 高阶函数 嵌套函数 最终: 高阶函数+嵌套函数 => 装饰器 四.函数即变量 1.

装饰器、生成器,迭代器、Json &amp; pickle 数据序列化

1. 列表生成器:代码例子 1 a=[i*2 for i in range(10)] 2 print(a) 3 4 运行效果如下: 5 D:\python35\python.exe D:/python培训/s14/day4/列表生成式.py 6 [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] 7 8 Process finished with exit code 0 2.高阶函数 变量可以指向函数,函数的参数能接受变量,即把一个函数名当做实参传给另外一个函数 返回值中包涵

Day4 - Python基础4 迭代器、装饰器、软件开发规范

Python之路,Day4 - Python基础4 (new版) 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>

装饰器-Day4

---恢复内容开始--- 一.装饰器的概述 装饰器本质是函数,用来装饰其他函数,顾名思义就是为其他函数添加附件功能. 二.装饰器的原则 不能修改被装饰函数的源代码 不能修改被装饰函数的调用方式 装饰器为什么会有这两个原则?因为如果写的程序在生产环境下已经运行了,修改别人的源代码或者别人的调用方式,后果可想而知. 三.实现装饰器的知识储备 函数即变量 高阶函数 嵌套函数 最终:高阶函数+嵌套函数=>装饰器 四.函数即变量 1.python的内存机制 x = 1 #变量 def test(): #函

Day4 - 迭代器&amp;生成器、装饰器、Json &amp; pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

python day4笔记 常用内置函数与装饰器

1.常用的python函数 abs             求绝对值 all               判断迭代器中所有的数据是否为真或者可迭代数据为空,返回真,否则返回假 any             判断迭代器中的数据是否有一个为真,有返回真,可迭代数据为空或者没有真,返回假 bin             转换整数为二进制字符串 hex            转换整数为十六进制字符串 oct             转换整数为八进制字符串 bool           转换数据为布尔值

Python Day4 函数 装饰器

内置函数: 参考 https://docs.python.org/2/library/functions.html 装饰器 装饰器是函数,只不过该函数可以具有特殊的含义,装饰器用来装饰函数或类,使用装饰器可以在函数执行前和执行后添加相应操作 # 定义函数,为调用,函数内部不执行 # 函数名 > 代指函数 # @ + 函数名 # 功能: #     1. 自动执行outer函数并且将其下面的函数名f1当作参数传递 #     2. 将outer函数的返回值,重复赋值给 f1 example 1: