如何在定义时自动注册一个类 [英] How to auto register a class when it's defined

查看:30
本文介绍了如何在定义时自动注册一个类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在定义类时注册一个类的实例.理想情况下,下面的代码可以解决问题.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆