我最近偶然发现了Python中的元类,并决定使用它们来简化某些功能。 (使用Python 3.5)Python3.5:使用继承进行类初始化
简而言之,我正在编写一个模块来定义类,例如必须注册和初始化的“组件”类(我的意思是我需要初始化实际的类,而不是实例)。
我可以很容易地注册类:
class MetaComponent(type):
def __init__(cls, *args, **kargs):
super().__init__(*args, **kargs)
RegisterComponent(cls)
class BaseComponent(metaclass=MetaComponent):
pass
class Component(BaseComponent):
"""This is the actual class to use when writing components"""
在这种情况下,我注册类的成分,因为它让我稍后查阅他们,没有他们的实际参考。
但类缺乏初始化自己(至少在Python 3.5)的能力,并可能导致一些问题,像这样的:
class Manager(Component):
SubManagers = []
@classmethod
def ListSubManagers(cls):
for manager in cls.SubManagers:
print(manager)
@classmethod
def RegisterSubManager(cls, manager):
cls.SubManagers.append(manager)
return manager
@Manager1.RegisterSubManager
class Manager2(Manager):
pass
@Manager2.RegisterSubManager
class Manager3(Manager):
pass
# Now the fun:
Manager1.ListSubManagers()
# Displays:
# > Manager2
# > Manager3
现在,这是一个问题,因为当时的想法是有一个每位经理的独特子管理员名单。但SubManager
字段在每个子类中共享...因此,添加到列表中会添加到每个子类中。安息。
所以接下来的想法是实现一种initializator的:
class BaseManager(Component):
@classmethod
def classinit(cls):
cls.SubManagers = []
但现在,我需要一种方法来调用类的创建后此方法。因此,让我们再次用metaclasses:
class MetaComponent(type):
def __init__(cls, *args, **kargs):
super().__init__(*args, **kargs):
cls.classinit(**kargs)
RegisterComponent(cls)
class BaseComponent(metaclass=MetaComponent):
@classmethod
def classinit(cls, **kargs):
print('BASE', cls)
class Component(BaseComponent):
@classmethod
def classinit(cls, **kargs):
super().classinit(**kargs) # Being able to use super() is the goal
print('COMPONENT', cls)
我会认为我自己这样做。有点做一个优雅的方式IMO。 classinit()
将从每个正在创建的类中调用(不同于在父级上调用的3.6 __init_subclass__
)。至少我很喜欢它,直到的Python 3.5 RuntimeError: super(): empty __class__ cell
哭了......
我读它是因为我打电话从元类的__init__
方法和方法虽然类的创建(因此我的意愿把代码__init__
,初始化已经创建的东西),它缺少这个__class__
单元格,至少在那一刻......至少在那一刻......
我试着在Python 3.6中运行完全相同的代码,并且它工作,所以我猜错了什么是错误的,但得到了修复...我的真正问题是:
- 我们可以真正用Python 3.5中的元类初始化类吗?
- 有没有办法避免在初始化过程中使用super()的限制?
- 它为什么在3.6中工作?
- 如果一切都失败了,那么仍然会提供类初始化并允许超级(...)调用的最佳方法是什么? (我是否需要明确提及超级类?)
感谢您的帮助提前。
编辑:
我们的目标是能够获得部件,并且能够类相对每个人的初始化至其母公司,在“易”的方式:
class Manager(Component):
def classinit(cls, **kargs):
cls.SubManagers = []
@classmethod
def RegisterSubManager(cls, manager):
cls.SubManagers.append(manager)
return manager
@Manager.RegisterSubManager
class EventManager(Manager):
def classinit(cls, **kargs):
super().classinit(**kargs) # keep the old behaviour
cls.Events = []
# ...
@EventManager.RegisterSubManager
class InputManager(EventManager):
def classinit(cls, **kargs):
super().classinit(**kargs) # again, keep old behaviour
cls.Inputs = []
# use parts of EventManager, but define specialized methods
# for input management
经理们一个问题,我有多个概念,这些概念依赖于组件以及它们初始化类的能力。
我不明白'@ Manager2.RegisterSubManager'可能可以工作,因为'Manager2'不是'Manager1'的子类。 – Blckknght
我的错误,修正了 – WKnight02