Python 不会自动将这些参数传递给已创建类的子类 - 正是由于以下原因,这可能更有用:
如果在创建子类时自动包含父类的参数,那么首先会出现的问题是:如何在最子类中合并所有超类的参数?
当然,显而易见的方法是遍历相反的方法解析顺序,并简单地将参数更新为字典,将最终值传递给最子类。
然而,这是 exact 使用普通旧继承的属性的行为 - 用户将无法进一步控制这些参数的传递方式。
通过使这些参数仅可用于实际构造的类,可以完全控制它们的使用方式,包括如何将它们传递给子类 - 如果您想让它们在子类中可用,只需创建它们作为父类的属性:
如果您希望语义与属性继承相同,则为每个关键字参数创建一个属性是“一种显而易见的方式”。您可能想为它们添加前缀,这样它们就不会与子类中的其他属性发生冲突:
prefix = "meta_"
class MyMeta(type):
def __new__(cls, name, bases, local, **kwargs):
# code to retrieve arguments from the bases:
# (N.B. this does not replicate the MRO algorithm)
for base in reversed(bases):
for name_ in dir(base):
if not name_.startswith(prefix):
continue
kwargs[name_[len(prefix):]] = getattr(base, name)
print(f'{name} got kwargs: {kwargs}')
for key, value in kwargs.items():
local[prefix + key] = value
return type.__new__(cls, name, bases, local)
class MyClass(metaclass=MyMeta, arg1="foo"):
pass
class MySubClass(MyClass):
pass
(请记住,类中的__init_subclass__ 也可以获取这些参数,并且可能您甚至不需要元类,具体取决于您想要的用途)
而且,如果您不需要完整的继承行为,您可以在创建的类中使用具有固定名称的简单字典来记录父类中所有传递的参数。
而且 - 上面的“收集超类参数”代码只是需要,因为我保留了您作为示例的行为,以便在调用 type.__new__ 之前获取参数 - 否则您可以在创建类后获取属性,在最终类中,让 Python 处理继承逻辑:
prefix = "meta_"
class MyMeta(type):
def __new__(cls, name, bases, local, **kwargs):
for key, value in kwargs.items():
local[prefix + key] = value
cls = super().__new__(cls, name, bases, local)
for name_ in dir(cls):
if not name_.startswith(prefix):
continue
print(f'{name} got custom parameter: {name_}: {getattr(cls, name_)}')
return cls
class MyClass(metaclass=MyMeta, arg1="foo"):
pass
class MySubClass(MyClass):
pass