背景
python每周一练20191103:使用Flask、Redis和Celery执行异步任务使用了@,有不少初学者对@犯疑。
image.png
装饰器decorator
返回值为另一函数的函数,通常使用 @wrapper语法。 装饰器的常见例子包括classmethod()
和 staticmethod()
。
装饰器语法只是一种语法快捷方式,以下两个函数定义在语义上完全等价:
def f(...):
...
f = staticmethod(f)
@staticmethod
def f(...):
...
同的样概念也适用于类,但通常较少这样使用。有关装饰器的详情可参见 函数定义 和 类定义 的文档。
- 示例1:
def test(f):
print("before ...")
f()
print("after ...")
@test
def func():
print("func was called")
执行结果
before ...
func was called
after ...
Python解释器读到函数修饰器“@”的时候,后面步骤会是这样了:
- 去调用 test函数,test函数的入口参数就是那个叫“func”的函数;
- test函数被执行,入口参数的(也就是func函数)会被调用(执行);
- 示例2:
def funcA(A):
print("function A")
def funcB(B):
print(B(2))
print("function B")
@funcA
@funcB
def func(c):
print("function C")
return c**2
执行结果
function C
4
function B
function A
这个例子告诉我们func有两个装饰器,是从下网上调用的。
注意:
- 函数先定义,再修饰它;反之会编译器不认识;
- 修饰符“@”后面必须是之前定义的函数或类;
- 每个函数可以有多个修饰符。
参考资料
- 本文最新版本地址
- 本文涉及的python测试开发库 谢谢点赞!
- 本文相关海量书籍下载
- python工具书籍下载-持续更新
- https://docs.python.org/3/howto/descriptor.html
- 本文配套视频 https://sn9.us/file/18113597-406685860 后面20分钟
描述器descriptor
任何定义了 __get__()
, __set__()
或 __delete__()
方法的对象。当类属性为描述器时,它的特殊绑定行为就会在属性查找时被触发。通常情况下,使用 a.b 来获取、设置或删除属性时会在 a 的类字典中查找名称为 b 的对象,但如果 b 是描述器,则会调用对应的描述器方法。理解描述器的概念是更深层次理解 Python 的关键,因为这是许多重要特性的基础,包括函数、方法、属性、类方法、静态方法以及对超类的引用等等。
有关描述符的方法的详情可参看 实现描述器。
class property(fget=None, fset=None, fdel=None, doc=None)
fget 是获取属性值的函数。 fset 是用于设置属性值的函数。 fdel 是用于删除属性值的函数。并且 doc 为属性对象创建文档字符串。
class C():
def __init__(self):
self._x = None
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
demo = C()
demo.x = 5
print(demo.x)
print(demo.getx())
执行结果
5
5
更快捷的方式:
class C():
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
demo = C()
demo.x = 5
print(demo.x)
@property 装饰器会将 x() 方法转化为同名的只读属性的 "getter",并将 x的文档字符串设置为 "I'm the 'x' property."
执行结果
5