我正在尝试编写一个通用的元类来跟踪子类
因为我希望这是通用的,我不想这个元类中硬编码任何类的名字,所以我想出了生成正确的元类,像一些功能:
def make_subtracker(root):
class SubclassTracker(type):
def __init__(cls, name, bases, dct):
print('registering %s' % (name,))
root._registry.append(cls)
super(SubclassTracker, cls).__init__(name, bases, dct)
return SubclassTracker
Run Code Online (Sandbox Code Playgroud)
这样我就可以调用它来为特定的根类生成一个元类:
__metaclass__ = make_subtracker(Root)
Run Code Online (Sandbox Code Playgroud)
这是我遇到问题的地方.我不能做到这一点:
class Root(object):
_registry = []
__metaclass__ = make_subtracker(Root)
Run Code Online (Sandbox Code Playgroud)
...因为Root
我使用时还没有定义make_subtracker(Root)
.我稍后尝试添加metaclass属性,以便至少可以在子类中应用它:
class Root(object):
_registry = []
Root.__metaclass__ = make_subtracker(Root)
Run Code Online (Sandbox Code Playgroud)
......但这不起作用.读取类定义时,metaclass有一个特殊的处理,如http://docs.python.org/reference/datamodel.html#customizing-class-creation中所定义
我正在寻找建议来做到这一点(在运行时以一种应用于其子类的方式更改类'元类,或任何其他替代方法).
aar*_*ing 10
我想你想要这样的东西(未经测试):
class SubclassTracker(type):
def __init__(cls, name, bases, dct):
if not hasattr(cls, '_registry'):
cls._registry = []
print('registering %s' % (name,))
cls._registry.append(cls)
super(SubclassTracker, cls).__init__(name, bases, dct)
Run Code Online (Sandbox Code Playgroud)
然后,对于Python 2,您可以像下面这样调用它:
class Root(object):
__metaclass__ = SubclassTracker
Run Code Online (Sandbox Code Playgroud)
对于Python 3
class Root(object, metaclass=SubclassTracker):
Run Code Online (Sandbox Code Playgroud)
请注意,您不需要_registry
在那里粘贴属性,因为像这样的东西是元类的用途.因为你已经碰巧有一个... ...)
另请注意,您可能希望将注册代码移动到else
子句中,以便该类不会将自身注册为子类.