python 装饰器和property
2020-12-07 02:50
标签:闭包函数 对象 style sed 结果 前缀 变量 htm init 所谓装饰器, 就是在代码执行期间, 在不改变原有代码(类或者函数)的情况下, 为之动态附加功能. 例如, 在调用函数之前做一些计算, 在函数调用之后输出日志. 如何实现一个装饰器呢, 这里就需要使用到前面学习的知识闭包函数了. 在装饰器原型中, 我们是手动的调用 expand 函数, 而在 python 中, 应该使用 @语法糖, 将装饰器 decorator 至于函数的定义处: 这时候, 我们就可以这样调用了 如果一个需要被装饰的函数有参数, 那么, 在装饰器的返回函数中, 也应该有有相应的参数, 否则会产生错误 如果装饰器本身需要传入参数, 那么就要再嵌套一层闭包 在以上的案例中, 我们会发现, 原函数被新函数替代, 原函数的签名__name__丢了, 文档__doc__等等也丢了, 取而代之的是返回的新函数的东西 而我们需要的是原函数, 而不是新的函数, 所以需要使用 functools.wraps 来将原函数的东西赋值给新的函数, 那么我们以上的例子就应该写为: 多层嵌套的装饰器, 不是很直观, 甚至很复杂, 那么我们就需要第三方库来优化, 让装饰器更具有可读性. 使用内置的装饰器: @decorator, 基本能够满足需求 被装饰之后, 我们去查看一下它的源码: 执行结果(是原函数的源码): wrapt 比较完善, 而且能够实现平常没有想到的装饰器, 使用的原型: 这里需要注意它的四个参数, 这四个参数是必须要有的, 而且 args 和 kwargs 不带星号, 在返回之时才带星号 由于小弟功力尚浅, 很少用 wrapt 这样的装饰器, 对此暂不做深入的演示, 如果你有兴趣, 可参考 wrapt 的文档: http://wrapt.readthedocs.io/en/latest/quick-start.html 由于在 python 中, 一切皆为对象, 函数形式的装饰器与类形式的装饰器相差不大, 所以对类的装饰器不做赘述. 以上内容的装饰器优化中, 使用的 @decorator 装饰器, 是其中的一个内置装饰器. 以下将介绍更多的常用的内置装饰器 在此, 我们想看看这样一个简单的类 在此类中, 封装了一个私有属性__name, 并定义了对__name属性的相关操作函数, 那么在我们没有使用 property 之前, 只能通过调用相应的方法才能对属性__name进行相关的操作. 那么我们使用了 property 之后, 我们就可以在外部这样操作: 那么当变量不断的增多时, 我们就要不断的增加一套一套的 get/set/del 和 property , 这样就会显得臃肿, 啰嗦, 而且有些私有的属性我们没有必要设置一套 get/set/del . 因此可以使用以下几个内置的装饰器来解决 了解至此, 我们可以把以上的 Person 类改写为这样: 在外部使用 总结: 类可以调用的方法有 静态方法, 类绑定方法和 普通方法. 实例可以调用的方法有 实例绑定方法, 类绑定方法 和 静态方法. python 装饰器和property 标签:闭包函数 对象 style sed 结果 前缀 变量 htm init 原文地址:https://www.cnblogs.com/trent-fzq/p/10989489.html一. 理解和实现装饰器
1. 装饰器的原型
import time
def decorator(func): # 将原函数作为参数传入
def newfunc():
# 调用之前
stime = time.perf_counter()
func() # 调用原函数
# 调用之后
etime = time.perf_counter()
print(‘called %s, used %s‘ % (func.__name__, etime-stime))
# 将新函数返回
return newfunc
def func():
print("原始函数被调用了")
func = decorator(func) # 手动的把新函数赋值给旧函数
func() # newfunc()
2. 装饰器的 @语法糖
@decorator # 相当于 func = expand(func)
def func():
print("原始函数被调用了")
func()
3. 被装饰函数带有参数的装饰器
import time
def decorator(func): # 将原函数作为参数传入
def newfunc(arg, *args, **kwargs):
# 调用之前
stime = time.perf_counter()
func(arg, *args, **kwargs) # 调用原函数
# 调用之后
etime = time.perf_counter()
print(‘called %s, used %s‘ % (func.__name__, etime-stime))
# 将新函数返回
return newfunc
@decorator
def func(arg, *args, **kwargs):
print("原始函数被调用了")
func(‘‘) # newfunc()
4. 带有返回值的装饰器函数
import time
def decorator(func):
def newfunc(arg, *args, **kwargs):
# stime = time.perf_counter()
return func(arg, *args, **kwargs) # 执行原函数, 并返回原函数的返回值
# etime = time.perf_counter()
# return etime-stime # 给原函数添加返回值功能
return newfunc
@decorator
def func(arg, *args, **kwargs):
return "原始函数被调用了"
print(func(‘‘)) # 0.0005786
5. 装饰器需要传参数
import time
def log(name):
def decorator(func):
def wrapper(*args, **kwargs):
print(‘%s call %s, on %s‘ % (name, func.__name__, time.strftime("%Y.%m.%d %H:%M:%S")))
return func(*args, **kwargs) # 执行原函数, 并返回原函数的返回值
return wrapper # 实际返回函数
return decorator
@log(‘trent‘) # 相当于执行了 func = log(‘trent‘)(func)
def func():
print("原始函数被调用了")
func()
6. 原函数丢失, 用 wraps 找回
def decorator(func):
def wrapper(*args, **kwargs):
pass
return wrapper
@decorator
def func():
pass
print(func.__name__) # wrapper
import time
from functools import wraps
def log(name):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print(‘%s called %s on %s‘ % (name, func.__name__, time.strftime("%Y.%m.%d %H:%M:%S")))
return func(*args, **kwargs) # 执行原函数, 并返回原函数的返回值
return wrapper # 实际返回函数
return decorator
7. 装饰器的优化 @decorator
import time
from decorator import decorator
def log(name):
@decorator
def dcrt(func, *args, **kwargs):
print(‘%s called %s on %s‘ %
(name, func.__name__, time.strftime("%Y.%m.%d %H:%M:%S")))
return func(*args, **kwargs)
return dcrt
@log(‘trent‘)
def func():
pass
func()
import inspect
print(inspect.getsource(func))
@log(‘trent‘)
def func():
pass
8. 一个强大的装饰器包 wrapt
import wrapt
@wrapt.decorator
def pass_through(wrapped, instance, args, kwargs):
return wrapped(*args, **kwargs)
@pass_through
def function():
pass
二. 常用的内置装饰器
class Person():
def __init__(self, name):
self.__name = name
def getName(self):
return self.__name
def setName(self, val):
self.__name = val
def delName(self):
del self.__name
name = property(getName, setName, delName, ‘a document‘)
ps = Person(‘Trent‘)
print(ps.name) # 相当于调用了ps.getName()函数
ps.name = ‘_trent_‘ # 相当于调用了ps.setName(‘_trent_‘)函数
print(ps.name)
del ps.name # 相当于调用了ps.delName()函数
1. @property 属性的获取
2. @setter 属性的赋值
3. @deleter 属性的删除
class Person():
def __init__(self, name):
self.__name = name
@property
def name(self):
return self.__name
@name.setter # 注意: setter必须带上前缀 公有的属性名.
def name(self, val):
self.__name = val
@name.deleter # 注意: deleter必须带上前缀 公有的属性名.
def name(self):
del self.__name
4. @classmethod
5. @staticmethod
class Person():
def run():
print(‘普通方法 run, 只能类调用‘)
def walk(self):
print(‘实例绑定方法 walk, 自动传递实例对象self参数‘)
@classmethod
def smile(cls):
print(‘类绑定方法 smile, 自动传递类cls参数‘)
@staticmethod
def look():
print(‘静态方法 look, 无论类和实例对象, 都能调用的方法‘)
ps = Person()
# ps.run() # 不能用实例对象调用
Person.run()
ps.walk()
# Person.walk() # 不能使用类调用
ps.smile()
Person.smile()
ps.look()
Person.look()
文章标题:python 装饰器和property
文章链接:http://soscw.com/index.php/essay/23418.html