【发布时间】:2019-05-02 22:19:35
【问题描述】:
我有一个元类,它定义了一个类级别属性,该属性对于每个子类应该是唯一的,但在每个子类的实例之间共享。
class MetaValidator(type):
def __new__(
cls, name, bases, dct
):
new_cls = super().__new__(cls, name, bases, dct)
new_cls.valid_funcs = []
return new_cls
现在我想实现一个装饰器,将装饰类方法附加到派生类中的valid_funcs。但是,因为派生类仍在定义中,所以我没有对派生装饰器的引用,所以我最终追加到基类。这是我的代码:
class Validator(object, metaclass=MetaValidator):
@classmethod
def add(cls, f):
cls.valid_funcs.append(f)
return f
def _validate(self, **kwargs):
for f in self.valid_funcs:
params = inspect.signature(f).parameters.keys()
f_kwargs = {name: kwargs[name] for name in params}
f(**f_kwargs)
def validate(self, **kwargs):
self._validate(**kwargs)
class A(Validator):
@staticmethod
@Validator.add
def test_func(x):
return x
class B(Validator):
@staticmethod
@Validator.add
def test_func(x, y):
return x, y
a = A()
a.validate(x="In A")
b = B()
b.validate(x="In B", y=" Called with arg y")
print(Validator.valid_funcs)
print(a.valid_funcs)
print(b.valid_funcs)
打印出来:
[<function A.test_func at 0x7f0189d4fc80>,
<function B.test_func at 0x7f0189d4fd08>]
[]
[]
我想要:
[]
[<function A.test_func at 0x7f0189d4fc80>]
[<function B.test_func at 0x7f0189d4fd08>]
【问题讨论】:
-
您使用元类是否有特定原因?为什么不简单地使用类装饰器添加类属性?
-
我也可以这样做,但是我必须将装饰器添加到每个派生类中,这更加麻烦。它也无助于 @add 装饰器的主要问题。如果使用装饰器而不是元类有帮助,那么我会接受它。
-
如果您使用的是 python 3.6+,则不需要这样做。您可以改用
__subclass_init__。容易得多。 -
哎呀抱歉:
__init_subclass__(我总是要查一下)
标签: python python-3.x decorator python-decorators metaclass