jsbueno 说了什么。我一直在尝试在 Python 2 中完成这项工作,但没有取得多大成功。这是我得到的最接近的:
class MetaTest(type):
_instances = {}
def __init__(cls, name, bases, attrs):
super(MetaTest, cls).__init__(name, bases, attrs)
MetaTest._instances[name] = cls()
class Foo(object):
__metaclass__ = MetaTest
class Bar(Foo):
pass
for name, obj in Bar._instances.items():
print name, obj, type(obj)
输出
Foo <__main__.Foo object at 0xb74626ec> <class '__main__.Foo'>
Bar <__main__.Bar object at 0xb746272c> <class '__main__.Bar'>
但是,如果您尝试提供 Foo 或 Bar __init__ 方法,那么由于 jsbueno 给出的原因,这一切都会崩溃。
这是一个 Python 3.6 版本,使用 super 的无参数形式,更成功:
class MetaTest(type):
_instances = {}
def __init__(cls, name, bases, attrs):
print('cls: {}\nname: {}\nbases: {}\nattrs: {}\n'.format(cls, name, bases, attrs))
super().__init__(name, bases, attrs)
MetaTest._instances[name] = cls()
class Foo(metaclass=MetaTest):
def __init__(self):
super().__init__()
class Bar(Foo):
def __init__(self):
super().__init__()
for name, obj in Bar._instances.items():
print(name, obj, type(obj))
输出
cls: <class '__main__.Foo'>
name: Foo
bases: ()
attrs: {'__module__': '__main__', '__qualname__': 'Foo', '__init__': <function Foo.__init__ at 0xb7192dac>, '__classcell__': <cell at 0xb718c2b4: MetaTest object at 0xb718d3cc>}
cls: <class '__main__.Bar'>
name: Bar
bases: (<class '__main__.Foo'>,)
attrs: {'__module__': '__main__', '__qualname__': 'Bar', '__init__': <function Bar.__init__ at 0xb7192d64>, '__classcell__': <cell at 0xb718c2fc: MetaTest object at 0xb718d59c>}
Foo <__main__.Foo object at 0xb712514c> <class '__main__.Foo'>
Bar <__main__.Bar object at 0xb71251ac> <class '__main__.Bar'>
我必须承认,我对类自动创建自己的实例的整个概念不太满意:“显式优于隐式”。我觉得 jsbueno 提出的使用注册功能的建议是一个很好的折衷方案。