day047函数之装饰器(闭包的运用),面向对象之单例模式(设计模式)

本节内容:

1、函数之装饰器
2、面向对象之单例模式

一、函数之装饰器(闭包的运用)

装饰器本质上就是一个python函数,一个闭包函数的运用,
他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。

装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。

1、装饰器的形成过程

现在有一个需求,要测试一个函数的执行时间,在不改变这个函数的执行情况下:

fe1:简单版的装饰器

简单版的装饰器

# 增加一个函数 测试其他函数执行效率的功能,但是尽量不要改变原函数的执行方式.

import time

def func(): # 被装饰的函数 time.sleep(0.2) print('10万行代码') def func1(): time.sleep(0.2) print('11万行代码') # func = 666 # func() def timmer(f): # func函数名 = f def inner(): start_time = time.time() f() end_time = time.time() print('此函数的执行效率为%s' % (end_time - start_time)) return inner func = timmer(func) # inner func() # inner() func1 = timmer(func1) func1() # 上个版本不行,每次执行被测试时间的函数时,必须要加一行代码. # 怎么解决,看下面的语法糖 
Python

fe2:装饰器—-语法糖

 装饰器:在不改变原函数的执行(代码机构基础上,给原函数增加一些额外的功能,登录验证,打印日志,测试效率等等.
 语法糖,就是python里面封装好的func = timmer(func),你直接调用就行,不用再自己写了

装饰器的语法糖运用

import time
def timmer(f): # func函数名 = f def inner(x,y): start_time = time.time() f(x,y) end_time = time.time() print('此函数的执行效率为%s' % (end_time - start_time)) return inner @timmer # func = timmer(func) def func(x,y): time.sleep(0.2) print(x + y) # 语法糖 @ # @timmer # func1 = timmer(func1) # def func1(): # print(666) func(10,20) # inner(10,20) # func1() 
Python

fe3:被装饰函数带参数,这时用无敌传参(*args, **kwargs)

无敌传参解决被装饰函数带参数

import time
def timmer(f): # func函数名 = f def inner(*args, **kwargs): # 传参,聚合 # args = (10,20) start_time = time.time() f(*args,**kwargs) # 被装饰函数的执行 * 打散 10 , 20 f(10,20) end_time = time.time() print('此函数的执行效率为%s' % (end_time - start_time)) return inner @timmer # func = timmer(func) func2 = timmer(func2) 这时的func2已经不是被装饰函数了 def func(x,y): time.sleep(0.2) print(x + y) @timmer def func2(x,y,z,w): print(x,y,z,w) # func(10, 20) # inner(10,20) func2(1,2,3,w=4) # 这里的参数被inner的f接收了,f就是语法糖传参的被装饰函数名 
Python

fe4: 标准的装饰器, 被装饰的函数带参数,带返回值

标准的装饰器

import time
def timmer(f): # func函数名 = f def inner(*args, **kwargs): # 接收被装饰函数的参数 start_time = time.time() ret = f(*args,**kwargs) # 接收被装饰函数执行之后的返回值 end_time = time.time() print('此函数的执行效率为%s' % (end_time - start_time)) return ret # 将返回值,返回给调用者 return inner @timmer # func = timmer(func) def func(x,y,z,e): time.sleep(0.2) return x + y + z + e ret1 = func(10, 30, 3, 4) # inner(10, 30) print(ret1) 
Python

2、面试题(手写一个装饰器)

def wrapper(f): def inner(*args, **kwargs): '''被装饰函数执行之前的操作''' ret = f(*args, **kwargs) """被装饰函数执行之后的操作""" return ret return inner 
Python

3、装饰器的应用: 登录验证.

需求:登陆后可以在各个页面切换

名字

dic_status = {
    'username': None, 'status': False, } def login(f): def inner(*args, **kwargs): '''被装饰函数执行之前的操作''' if dic_status['status'] : ret = f(*args, **kwargs) return ret else: username = input('请输入用户名').strip() password = input('请输入密码').strip() with open('register', encoding='utf-8') as f1: for line in f1: user, pwd = line.split('|') if username == user.strip() and password == pwd.strip(): dic_status['username'] = username dic_status['status'] = True print('登录成功,正在跳转...') ret = f(*args, **kwargs) return ret else: print('登录失败...') return inner @login def article(): print('欢迎登录文章页面') @login def diary(): print('欢迎登录日记页面') @login def comment(): print('欢迎登录评论页面') dic = { 1: article, 2: diary, 3: comment, } while 1: num = input('欢迎访问博客园,请选择:\n1文章页面 \n2 日记页面 \n 3 评论页面').strip() if num.isdigit(): dic[int(num)]() else: print('重新输入..') # 还需写一个register的文件来放用户信息,进行登录验证 
Python

4、带参数的装饰器

带参数的装饰器

import time
def timmer(flag): # 这个函数的作用是,将参数传给装饰器函数 def wrapper(f): # 这个函数的作用是:将被装饰函数作为参数传入 def inner(*args, **kwargs): # 传入被装饰函数的参数,传参 if flag: # 通过这个状态来,控制是否执行装饰器函数 start_time = time.time() ret = f(*args, **kwargs) end_time = time.time() print('执行时间%s' % (end_time-start_time)) return ret else: ret = f(*args, **kwargs) return ret return inner return wrapper flag1 = False @timmer(flag1) # 第一步,将@ 与后面 分开,只是单纯的执行timmer(flag1)函数 第二部 将@ 与 wrapper相结合,形成装饰器 def func1(): time.sleep(0.3) print('in func1') func1() 
Python

5、多个装饰器 装饰一个函数

多个装饰器 装饰一个函数

def wrapper1(func): # func == f 函数名 def inner1(): print('wrapper1 ,before func') # 2 func() print('wrapper1 ,after func') # 4 return inner1 def wrapper2(func): # func == inner1 def inner2(): print('wrapper2 ,before func') # 1 func() print('wrapper2 ,after func') # 5 return inner2 # 就近原则 先将近的传给装饰器函数,多个装饰器的话,逐层上传 @wrapper2 # f = wrapper2(f) 里面f == inner1 外面的f == inner2 @wrapper1 # f = wrapper1(f) 里面的f == 函数名f 外面的f == inner1 def f(): print('in f') # 3 f() # inner2() 
Python

二、面向对象之单例模式

就是只能实例化一个对象,不管创建多少个对象,都是指向同一个内存地址

例如:多个py文件在引入同一个模块,如果没有设置

1、单例模式代码示例

class A:
    __instance = None # 定义一个私有变量, def __new__(cls, *args, **kwargs): # 通过重写父类的__new__方法,来控制指向第一个实例化对象的地址 if A.__instance is None: # 通过私有变量来控制指向第一个实例化对象的(同一个)的地址 obj = object.__new__(cls) # 如果是第一次实例化对象,就创建对象, A.__instance = obj return A.__instance # 如果不是第一次,就直接指向第一次对象的内存地址,不再创建对象 obj1 = A() obj2 = A() obj3 = A() obj4 = A() print(obj1) # 都指向同一个内存地址 print(obj2) print(obj3) print(obj4)

猜你喜欢

转载自www.cnblogs.com/yipianshuying/p/10153645.html