【发布时间】:2017-04-03 15:41:52
【问题描述】:
我有一个自己编写的基于类的 Python 装饰器。据我所知,当我将装饰器应用于类中的方法时,存在差异。通常,像@classmethod、@staticmethod、@property 或@unique 这样的装饰器在应用时不带括号。这些装饰器不需要参数,并且(大部分?)编写为基于函数的装饰器。
因此,与这些示例相比,我的装饰器是基于类的,并且在应用时需要一个可选参数。
我的装饰师:
class DocumentMemberAttribute(Attribute):
def __init__(self, value=True):
super().__init__()
self.value = value
Attributes 类(真正的装饰器):
class Attribute:
__AttributesMemberName__ = "__pyattr__"
def __call__(self, func):
self._AppendAttribute(func, self)
return func
@staticmethod
def _AppendAttribute(func, attribute):
# inherit attributes and append myself or create a new attributes list
if (Attribute.__AttributesMemberName__ in func.__dict__):
func.__dict__[Attribute.__AttributesMemberName__].append(attribute)
else:
func.__setattr__(Attribute.__AttributesMemberName__, [attribute])
def __str__(self):
return self.__name__
示例类:
class MyClass:
def __init__(self, message=""):
super().__init__()
self.message = message
@DocumentMemberAttribute
def Method1(self):
return "foo"
@DocumentMemberAttribute()
def Method2(self):
return "bar"
@DocumentMemberAttribute(False)
def Method3(self):
return "spam"
@DocumentMemberAttribute(True)
def Method4(self):
return "egg"
附加信息用于自定义autodoc-skip-member 处理程序,以决定是否应记录或跳过方法。这类似于docit 扩展。
所以当我们查看生成的文档(Sphinx)时,我们可以看到这些结果:
类 MyClass(message="")
Method1 =
方法2()
Method4()
我们可以在这里看到什么:
- Method1 没有括号表示函数/方法,因此它被视为一个类字段,Sphinx 使用
__str__(或__repr__?)来记录初始值 - 方法 3 未按预期记录。
所以我的问题:
- 为什么会有不同的行为?
- 我必须应用带括号的基于类的属性吗?
- 用户应该如何知道如何使用这两种装饰器? (我可以自己记录,但其他人可能只记得名字而忘记添加括号,因为其他装饰器不需要它们。)
pyAttributes是我写的一组属性(真实属性,没有Python属性)。它们的行为几乎类似于 .NET 中的 custom-attributes
【问题讨论】:
-
与大多数装饰定义一样,
@test等同于@Test()的含义,没有参数。例如,我使用 Dart 语言中的装饰器,因为它需要利用它们与前端标记进行交互。我必须对注释及其用途以及它们的用途/用途进行大量研究 -
装饰器评估一个表达式(
@之后的那个)并调用该表达式的结果,将装饰项作为参数传递并用返回值替换它。func与func()不同,所以@func与@func()不同。 -
click.pocoo.org/5 顺便说一句,在不尝试将 .NET 惯用语融入 Python 的情况下执行自述文件中描述的方法。
-
@Ryan 是的,
@deco \n class foo:被翻译成class foo: \n foo = deco(foo)。我注意到 PyCharm 将基于函数的装饰器涂成蓝色,将基于类的装饰器涂成红色。除此之外,用户应该如何知道如何调用/应用装饰器? -
是的。对于任何
expr,@expr class foo:是foo = (expr)(foo),所以deco()(foo)是正确的。
标签: custom-attributes python-3.x custom-data-attribute python-decorators default-parameters