您的当前位置:首页正文

python闭包(装饰器)参数传递及实现单列模式

来源:我们爱旅游
python闭包(装饰器)参数传递及实现单列模式

被装饰器装饰的函数名即使没有被调⽤(因为有@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]。

因篇幅问题不能全部显示,请点此查看更多更全内容