西湖区外贸网站建设,手机网站定制建设,10大物业管理系统,手机网页开发者模式目录
❤ python装饰器介绍
❤ 什么是装饰器
❤ 装饰器的流程
❤ 定义装饰器时通常会涉及以下3个函数
无参装饰器
有参装饰器
多重装饰器
❤ 装饰器的用法(闭包)
❤ 装饰器语法糖
❤ 时间计时器
❤ 装饰器中wraps作用
不使用wraps装饰器
使用wraps装饰器解…目录
❤ python装饰器介绍
❤ 什么是装饰器
❤ 装饰器的流程
❤ 定义装饰器时通常会涉及以下3个函数
无参装饰器
有参装饰器
多重装饰器
❤ 装饰器的用法(闭包)
❤ 装饰器语法糖
❤ 时间计时器
❤ 装饰器中wraps作用
不使用wraps装饰器
使用wraps装饰器解决这个问题
❤ 装饰器顺序
❤ 类的装饰器 - classmethod
绑定到对象的方法
绑定到类的方法
❤ 类的装饰器 - property
❤ 类的装饰器 - staticmethod ❤ python装饰器介绍
在Python中装饰器decorator是在闭包的基础上发展起来的。装饰器的实质是一个高阶函数其参数是要装饰的函数名其返回值是完成装饰的函数名其作用是为已经存在的函数对象添加额外的功能其特点是不需要对原有函数做任何代码上的变动。装饰器在本质上也是一个嵌套函数其外层函数的返回值是一个新的函数对象引用所不同的是其外层函数可以接受一个现有函数对象引用作为参数。装饰器可以用于包装现有函数即在不修改任何代码的前提下为现有函数增加额外功能。装饰器通常应用于有切面面向切面编程是指运行时动态实现程序维护的一种技术需求的场景例如插入日志、性能测试、事务处理、缓存以及权限校验等。装饰器是解决这类问题的绝佳设计有了装饰器就可以抽离出大量与函数功能本身无关的雷同代码并继续重用它们。
❤ 什么是装饰器
装饰是为函数和类指定管理代码的一种方式。Python装饰器以两种形式呈现
函数装饰器在函数定义的时候进行名称重绑定。提供一个逻辑层来管理函数和方法或随后对它们的调用。类装饰器在类定义的时候进行名称重绑定提供一个逻辑层来管理类。或管理随后调用它们所创建的实例。
❤ 装饰器的流程
A函数是装饰器B函数是A函数传入的参数。 将B函数在A函数中执行在A函数中可以选择执行或不执行也可以对B函数的结果进行二次加工处理。
简而言之装饰器提供了一种方法在函数和类定义语句的末尾插入自己主动执行的代码——对于函数装饰器。在def的末尾。对于类装饰器在class的末尾。
这种代码能够扮演不同的角色。 装饰器提供了一些和代码维护性和审美相关的有点。此外作为结构化工具装饰器自然地促进了代码封装这降低了冗余性并使得未来变得更easy。
❤ 定义装饰器时通常会涉及以下3个函数:
1装饰器函数它在函数嵌套关系中作为外层函数出现其函数体内容包括定义一个内层函数以完成装饰功能的函数通过return语句向调用者返回内层函数对象引用。 2目标函数即需要进行装饰的函数它作为装饰器函数的形参出现该函数的定义则出现在调用装饰器的地方。 3完成装饰的函数它在函数嵌套关系中作为内层函数出现用于为待装饰的目标函数添加额外功能。在这个内层函数中要调用目标函数并为目标函数添加一些新的功能
无参装饰器
def 装饰器名称(待装饰器函数名称):def 装饰器函数名称():# 目标函数执行前 添加额外功能# 目标函数调用 待装饰器函数执行# 目标函数执行后 添加额外功能return 装饰器函数名称def decorator(func):def inner(*args, **kwargs):# func是被装饰的对象这里可以写执行前的功能res func(*args, **kwargs)# func是被装饰的对象这里可以写执行后的功能return inner# 使用装饰器装饰器名称
def 需装饰函数名称():pass无参数装饰器本质就是一个双层结构的高阶函数有参数装饰器则是一个3层结构的高阶函数。
有参装饰器
def 装饰器名称(参数1 参数2...):def 中间层装饰器函数名称(待装饰器函数名称)def 里层装饰器函数名称():# 目标函数执行前 添加额外功能# 目标函数调用 待装饰器函数执行# 目标函数执行后 添加额外功能return 装饰器函数名称return 中间层装饰器函数名称def decorator(arg1, arg2):def middle(func):def inner(*args, **kwargs):# func是被装饰的对象这里可以写执行前的功能 可使用参数 arg1, arg2res func(*args, **kwargs)# func是被装饰的对象这里可以写执行后的功能 可使用参数 arg1, arg2return innerreturn middle# 使用装饰器装饰器名称(arg1, arg2)
def 需装饰函数名称():pass
多重装饰器
多重装饰器是指使用多个装饰器来修改同一个函数。此时要注意多重装饰器的执行顺序是后面的装饰器先执行前面的装饰器后执行即后来者居上
def first(func):def inner(*args, **kwargs):print(函数first执行...)func(*args, **kwargs)print(函数first完成)return innerdef second(func):def inner(*args, **kwargs):print(函数second执行...)func(*args, **kwargs)print(函数second完成)return inner# 两装饰器应用于同一函数first
second
def test():print(函数test执行)# 执行结果函数first执行...
函数second执行...
函数test执行
函数second完成
函数first完成❤ 装饰器的用法(闭包)
闭包Closure又称词法闭包Lexical Closure或函数闭包function closures是引用了自由变量的函数。
这个被引用的自由变量将和这个函数一同存在即使已经离开了创造它的环境也不例外。
def print_msg(): # print_msg是外围函数msg Im closuredef printer(): # printer是嵌套函数print(msg)return printerclosure print_msg() # 这里获得的就是一个闭包
closure() # 输出 Im closure
msg是一个局部变量在print_msg函数执行之后就不会存在了。
但是嵌套函数引用了这个变量将这个局部变量封闭在了嵌套函数中这样就形成了一个闭包。
❤ 装饰器语法糖
语法糖Syntactic sugar也译为糖衣语法指计算机语言中添加的某种语法。
这种语法对语言的功能并没有影响但是更方便程序员使用。
通常来说使用语法糖能够增加程序的可读性从而减少程序代码出错的机会。 符号是装饰器的语法糖。它放在一个函数开始定义的地方头顶和这个函数绑定在一起。
在我们调用这个函数的时候会先将这个函数做为参数传入它头顶即装饰器里。
❤ 时间计时器
以下用装饰器来实现计算一个函数的执行时长让函数睡眠3秒
# 这是装饰函数
def timer(func):def wrapper(*args, **kw):start_time time.time()func(*args, **kw) # 这是函数真正执行的地方stop_time time.time()cost_time stop_time - start_timeprint(花费时间{}秒.format(cost_time))return wrapperimport timetimer
def want_sleep(sleep_time):time.sleep(sleep_time)want_sleep(3)
❤ 装饰器中wraps作用
装饰器decorator在实现的时候被装饰后的函数其实已经是另外一个函数了函数名等函数属性会发生改变。
为了不影响Python的functools包中提供了一个叫wraps的装饰器来消除这样的副作用。
写一个装饰器的时候最好在实现之前加上functools中的wraps它能保留原有函数的名称和文档字符串(DocStrings)。
文档字符串用于解释文档程序帮助程序文档更加简单易懂。
可以在函数体的第一行使用一对三个单引号 ‘’’ 或者一对三个双引号 “” 来定义文档字符串。
使用 doc注意双下划线调用函数中的文档字符串属性。
不使用wraps装饰器
def decorator(func):this is decorator __doc__def wrapper(*args, **kwargs):this is wrapper __doc__print(this is wrapper method)return func(*args, **kwargs)return wrapperdecorator
def test():this is test __doc__print(this is test method)print(__name__: , test.__name__)
print(__doc__: , test.__doc__)
输出: __name__: wrapper __doc__: this is wrapper __doc__ 分析 对test()方法进行装饰时候实际上是
test decorator(test)
返回的是wrapper方法的引用也就是让test指向了wrapper方法所以调用test.name, 实际上是wrapper.name。
这造成后面查找该方法的名字和注释时得到装饰器内嵌函数的名字和注释。
使用wraps装饰器解决这个问题 from functools import wrapsdef decorator(func):this is decorator __doc__wraps(func)def wrapper(*args, **kwargs):this is wrapper __doc__print(this is wrapper method)return func(*args, **kwargs)return wrapperdecorator
def test():this is test __doc__print(this is test method)print(__name__: , test.__name__)
print(__doc__: , test.__doc__)
输出: __name__: test __doc__: this is test __doc__ ❤ 装饰器顺序
一个函数可以同时定义多个装饰器比如
a
b
c
def f ():pass它的执行顺序是从里到外最先调用最里层的装饰器最后调用最外层的装饰器它等效于
f a(b(c(f)))
❤ 类的装饰器 - classmethod
classmethod ***** 类的对象绑定的方法都是默认传self参数的但是当这个self在方法中不被使用时 然后在方法中准备使用类的静态属性就可以将该方法修改为类方法在外部可以不用实例化对象直接通过类名调用类方法
绑定到对象的方法
在类内部没有任何修饰的情况下直接定义一个方法默认绑定一个self给对象来用
class Mysql:def __init__(self,host,port):self.hosthostself.portportdef tell_info(self): print(%s:%s %(self.host,self.port))conn1Mysql(127.0.0.1,8080)
conn1.tell_info()
输出: 127.0.0.1:8080 绑定到类的方法
当函数体代码需要传进来的参数不再是对象了而是类的时候
以下是实现从配置文件里读IP和端口完成实例化的程序 settings import settingsclass Mysql:def __init__(self,host,port):self.hosthostself.portportdef tell_info(self):print(%s:%s %(self.host,self.port))classmethod #绑定给类由类来掉把它当做第一个参数传进来完成实例化再把结果返回def from_conf(cls):return cls(settings.HOST, settings.PORT)conn2Mysql.from_conf()printconn2.tell_info
conn2.tell_info()# 打印结果bound method Mysql.tell_info of __main__.Mysql object at 0x00C9CFF0 1.1.1.1:8080
我们得出以下结论
在带有 classmethod 装饰器 的 函数 内是无法调用普通的 带有 self 的函数的但是在普通的带有 self 的类函数内是可以调用带有 classmethod 装饰器 的 函数的❤ 类的装饰器 - property
property是一种特殊的属性可实现把函数名变为属性名使用。它可以在不改变类接口的前提下使用存取方法 (即读值和取值)
来修改数据的属性property类有3个方法getter读操作、setter赋值操作、deleter删除操作分别把对应的操作
绑定到指定的函数实现应用如下
class People:def __init__(self,name,weight,height):self.namenameself.wtweightself.htheightpropertydef bmi(self):return self.wt / (self.ht ** 2)property #便于用户访问隐藏的内部值namedef name(self):return self.__namename.setter #便于用户 修改name值def name(self,obj): #objEGONif not isinstance(obj,str):raise TypeError(名字的值必须是str类型)self.__nameobj #self.__nameEGONname.deleterdef name(self):del self.__namepPeople(egon,75,1.80)
# print(p.bmi)# print(p.name)
# p.nameEGON
# p.name123 #报错
# print(p.name)# del p.name #删除name
❤ 类的装饰器 - staticmethod
非绑定方法不与任何东西绑定定义的函数不需要任何东西传进来
import uuidclass Mysql:def __init__(self,host,port):self.hosthostself.portportstaticmethoddef create_id():return uuid.uuid4()print(Mysql.create_id)
print(Mysql.create_id())#打印结果function Mysql.create_id at 0x02C6EC90 2209806a-5ffc-47f2-86f1-cb2ac64ce404
整体代码
import settings
import uuidclass Mysql:def __init__(self,host,port):self.hosthostself.portportdef tell_info(self):print(%s:%s %(self.host,self.port))classmethoddef from_conf(cls):return cls(settings.HOST, settings.PORT)staticmethoddef create_id():return uuid.uuid4()conn1Mysql(127.0.0.1,8080)
conn1.tell_info()conn2Mysql.from_conf()
conn2.tell_info()
print(conn2.tell_info)print(Mysql.create_id)
print(Mysql.create_id())#打印结果127.0.0.1:8080 1.1.1.1:8080 bound method Mysql.tell_info of __main__.Mysql object at 0x038294B0 function Mysql.create_id at 0x03831E40 bab5e25e-7de3-4273-a8cf-40829c716d87
附使用最广泛的装饰器为 classmethod