如何在定义时自动注册一个类 [英] How to auto register a class when it's defined
问题描述
我想在定义类时注册一个类的实例.理想情况下,下面的代码可以解决问题.
I want to have an instance of class registered when the class is defined. Ideally the code below would do the trick.
registry = {}
def register( cls ):
registry[cls.__name__] = cls() #problem here
return cls
@register
class MyClass( Base ):
def __init__(self):
super( MyClass, self ).__init__()
不幸的是,此代码生成错误NameError: global name 'MyClass' is not defined
.
Unfortunately, this code generates the error NameError: global name 'MyClass' is not defined
.
发生了什么在 #problem here
行我试图实例化一个 MyClass
但装饰器还没有返回所以它不存在.
What's going on is at the #problem here
line I'm trying to instantiate a MyClass
but the decorator hasn't returned yet so it doesn't exist.
是使用元类还是其他方法来解决这个问题?
Is the someway around this using metaclasses or something?
推荐答案
是的,元类可以做到这一点.元类的 __new__
方法返回该类,因此只需在返回该类之前注册该类.
Yes, meta classes can do this. A meta class' __new__
method returns the class, so just register that class before returning it.
class MetaClass(type):
def __new__(cls, clsname, bases, attrs):
newclass = super(MetaClass, cls).__new__(cls, clsname, bases, attrs)
register(newclass) # here is your register function
return newclass
class MyClass(object):
__metaclass__ = MetaClass
上一个示例适用于 Python 2.x.在 Python 3.x 中,MyClass
的定义略有不同(而 MetaClass
没有显示,因为它没有改变——除了 super(MetaClass, cls)
可以变成 super()
如果你愿意):
The previous example works in Python 2.x. In Python 3.x, the definition of MyClass
is slightly different (while MetaClass
is not shown because it is unchanged - except that super(MetaClass, cls)
can become super()
if you want):
#Python 3.x
class MyClass(metaclass=MetaClass):
pass
从 Python 3.6 开始,还有一个新的 __init_subclass__
方法(参见 PEP 487) 可以用来代替元类(感谢@matusko 在下面的回答):
As of Python 3.6 there is also a new __init_subclass__
method (see PEP 487) that can be used instead of a meta class (thanks to @matusko for his answer below):
class ParentClass:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
register(cls)
class MyClass(ParentClass):
pass
这篇关于如何在定义时自动注册一个类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!