被装饰器装饰的函数名即使没有被调⽤(因为有@xxx,会触发运⾏装饰器),(装饰器⼯⼚函数)定义装饰器的代码已经运⾏了(最内部的那个函数并没有运⾏)(把被装饰的原函数引⽤赋值给了装饰器内部的那个函数名),当下边通过该函数名调⽤时,会调⽤到装饰器内部的那个函数()
装饰器:在不修改函数源代码的基础上,添加函数功能⼀个简单的装饰器
1
def log_time(func): # 此函数的作⽤时接受被修饰的函数的引⽤test,然后被内部函数使⽤2
def make_decorater():3 print('现在开始装饰')4 func()
5 print('现在结束装饰')
6 return make_decorater # log_time()被调⽤后,运⾏此函数返回make_decorater()函数的引⽤make_decorater7
8@log_time # 此⾏代码等同于,test=log_time(test)=make_decorater9def test():
10 print('我是被装饰的函数')
test() # test()=make_decorater()11
1D:\\pycharm_project\\装饰器\\venv\\Scripts\\python.exe D:/pycharm_project/装饰器/venv/装饰器.py2现在开始装饰
3我是被装饰的函数4现在结束装饰5
Process finished with exit code 06
当被装饰的函数有形参时
1def log_time(func):
2 def make_decorater(*args,**kwargs): # 接受调⽤语句的实参,在下⾯传递给被装饰函数(原函数)3 print('现在开始装饰')
4 test_func = func(*args,**kwargs) # 如果在这⾥return,则下⾯的代码⽆法执⾏,所以引⽤并在下⾯返回5 print('现在结束装饰')
6 return test_func # 因为被装饰函数⾥有return,所以需要给调⽤语句(test(2))⼀个返回,⼜因为test_func = func(*args,**kwargs)已经调⽤了被装饰函数,这⾥就不⽤带()调⽤了,区别在于运⾏顺序的不同。7
return make_decorater8 9
10@log_time11def test(num):
12 print('我是被装饰的函数')13 return num+114
15a = test(2) # test(2)=make_decorater(2)16print(a)1
D:\\pycharm_project\\装饰器\\venv\\Scripts\\python.exe D:/pycharm_project/装饰器/venv/装饰器.py2现在开始装饰
3我是被装饰的函数4现在结束装饰536
Process finished with exit code 07
当@装饰器后有参数时12345
def get_parameter(*args,**kwargs): # ⼯⼚函数,⽤来接受@get_parameter('index.html/')的'index.html/' def log_time(func): def make_decorater(): print(args,kwargs) print('现在开始装饰') func()
print('现在结束装饰')
67
8 return make_decorater9 return log_time10
@get_parameter('index.html/')11
def test():
11
def test():
12 print('我是被装饰的函数')13 # return num+114
15test() # test()=make_decorater()161
D:\\pycharm_project\\装饰器\\venv\\Scripts\\python.exe D:/pycharm_project/装饰器/venv/装饰器.py2('index.html/',) {}3现在开始装饰
4我是被装饰的函数5现在结束装饰6
Process finished with exit code 07
两个装饰器同时修饰⼀个函数(重点看执⾏顺序)
1def log_time1(func):
2 def make_decorater(*args,**kwargs): 3 print('1现在开始装饰')
4 test_func = func(*args,**kwargs) 5 print('1现在结束装饰') 6 return test_func 7 return make_decorater8
9def log_time2(func):
10 def make_decorater(*args,**kwargs): # 接受调⽤语句的实参,在下⾯传递给被装饰函数(原函数)11 print('2现在开始装饰')
12 test_func = func(*args,**kwargs) # 如果在这⾥return,则下⾯的代码⽆法执⾏,所以引⽤并在下⾯返回13 print('2现在结束装饰')
return test_func # 因为被装饰函数⾥有return,所以需要给调⽤语句(test(2))⼀个返回,⼜因为test_func = func(*args,**kwargs)已经调⽤了被装饰函数,这14
⾥就不⽤带()调⽤了,区别在于运⾏顺序的不同。15 return make_decorater16
17@log_time118@log_time219def test(num):
20 print('我是被装饰的函数')21 return num+122
23a = test(2) # test(2)=make_decorater(2)24print(a)1
2D:\\pycharm_project\\装饰器\\venv\\Scripts\\python.exe D:/pycharm_project/装饰器/venv/装饰器.py1现在开始装饰32现在开始装饰4我是被装饰的函数52现在结束装饰61现在结束装饰37
8Process finished with exit code 09
注意看执⾏结果(print,只有执⾏就会输出到屏幕)(return将数据返回给接受的变量或引⽤)
def makeBold(fn):
1 def wrapped1():
2 print('1')
3 b = \"\" + fn() + \"\" # 此⾏fn()调⽤了wrapped(),所以wrapped()执⾏了print输出到屏幕,然后fn()接受到了wrapped() return返回的结果\"\" + fn() + \"\",4所以需要等待wrapped()
print('1end') # 只有b = \"\" + fn() + \"\"执⾏完毕才会执⾏这⼀⾏,只有wrapped()函数 return返回后,上⼀⾏代码才执⾏
return b5
return wrapped16 7
def makeItalic(fn):8
def wrapped():9 print('2')
10 a = return \"\" + fn() + \"\" # 此⾏fn()调⽤了test3(),所以test3()执⾏了,然后fn()接受到了test3()中returnd返回的结果\"hello world-3\",所以需要等待11test3
print('2end') # 当test3()返回后,上⼀⾏代码执⾏完毕,在屏幕上输出此⾏
return a12 return wrapped13
13
14@makeBold15@makeItalic16def test3():
17 return \"hello world-3\" # return 给了wrapped,wrapped⼜return给了wrapped;18
19a = test3() # 此⾏test3() = wrapped1(),test3()调⽤了函数所以装饰器才执⾏。a接受了装饰器return的结果
print(a)
1D:\\pycharm_project\\装饰器\\venv\\Scripts\\python.exe D:/pycharm_project/装饰器/venv/text.py21
32
2end
1end
4hello world-35
Process finished with exit code 06
Python中单例模式的实现⽅法有多种,但在这些⽅法中属装饰器版本⽤的⼴,因为装饰器是基于⾯向切⾯编程思想来实现的,具有很⾼的解耦性和灵活性。
单例模式定义:具有该模式的类只能⽣成⼀个实例对象。先将代码写上
#创建实现单例模式的装饰器1 def singleton (cls, *args, **kwargs):2 instances = {}
3 def get_instance (*args, **kwargs):4 if cls not in instances:
5 instances[cls] = cls(*args, **kwargs)6 return instances[cls]7 return get_instance
代码分析:第1⾏,创建外层函数singleton,可以传⼊类 第2⾏,创建⼀个instances字典⽤来保存单例 第3⾏,创建⼀个内层函数来获得单例
第4,5,6⾏, 判断instances字典中是否含有单例,如果没有就创建单例并保存到instances字典中,然后返回该单例 第7⾏, 返回内层函数get_instance #创建⼀个带有装饰器的类 @singleton class Student:
def __init__(self, name, age): self.name = name self.age = age
在Python中认为“⼀切皆对象”,类(元类除外)、函数都可以看作是对象,既然是对象就可以作为参数在函数中传递,我们现在来调⽤Student类来创建实例,看看实现过程。#创建student实例
student = Student(jiang, 25)
@singleton相当于Student = singleton(Student),在创建实例对象时会先将 Student 作为参数传⼊到 singleton 函数中,函数在执⾏过程中不会执⾏ get_instance 函数(函数只有调⽤才会执⾏),直接返回get_instance函数名。
此时可以看作Student = get_instance,创建实例时相当于student = get_instance(jiang, 25),调⽤get_instance 函数,先判断实例是否在字典中,如果在直接从字典中获取并返回,如果不在执⾏ instances [cls] = Student(jiang, 25),然后返回该实例对象并赋值⾮student
变量,即student = instances[cls]。
因篇幅问题不能全部显示,请点此查看更多更全内容