[英]Is there a way to reference an object's base __class__ from class scope?
我有一系列的类,继承自几个可能的父类中的一个,它们都共享一个基数 class。每个 class 都有一个基于基数 class parameters
的类作用域 Dict[str, object] parameters
from copy import deepcopy
class BaseClass:
parameters = {
'example_param1': ParamObject(name='example_param1', editable=True),
}
class MiddleClass(Baseclass):
parameters = {
**deepcopy(Baseclass.parameters),
'example_param2': ParamObject(name='example_param2', editable=False),
}
class ChildClass(MiddleClass):
parameters = {
**deepcopy(MiddleClass.parameters),
'example_param3': ParamObject(name='example_param3', editable=True),
}
这个实现完成了工作,但我发现**deepcopy(Baseclass.parameters),
行不令人满意。 随着时间的推移,这些子类将由只对编码有基本了解的人进行编辑,所以我想让代码尽可能简单,并且可以剪切和粘贴。
有什么我可以拨打 class scope 来获得super().__class__
的等价物吗? 我希望用户能够将基数 class 从MiddleClass
更改为MiddleClass2
,而无需记住在多个位置更改基数 class。
您可以使用__init_subclass__
将父类中的参数直接添加到显式定义的parameters
属性中,但代价是插入顺序被颠倒(如果这很重要)。
class ParameterBase:
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
for pc in cls.__bases__:
d = getattr(pc, 'parameters', {})
cls.parameters.update(d)
class BaseClass(ParameterBase):
parameters = {
'example_param1': ParamObject(name='example_param1', editable=True),
}
class MiddleClass(BaseClass):
parameters = {
'example_param2': ParamObject(name='example_param2', editable=False),
}
class ChildClass(MiddleClass):
parameters = {
'example_param3': ParamObject(name='example_param3', editable=True),
}
你可以用元类来做到这一点。 检查 inheritance 树中的所有类,看它们是否具有parameter
s 字段。 如果是,则将它们合并在一起并在 class 实例上设置属性。
class ParamMeta(type):
def __init__(cls, name, bases, dct):
class_types = [cls] + list(bases)
parameters = {}
for class_type in class_types:
if hasattr(class_type, "parameters"):
parameters.update(class_type.parameters)
cls.parameters = parameters
super().__init__(name, bases, dct)
例子:
class Foo(metaclass=ParamMeta):
parameters = {"a": "b"}
class Bar(Foo):
pass
class Fizz(Bar):
parameters = {"c": "d"}
print(Foo.parameters)
print(Bar.parameters)
print(Fizz.parameters)
输出:
{'a': 'b'}
{'a': 'b'}
{'c': 'd', 'a': 'b'}
如果您的 class 仅继承自一个 class,则可以使用元类:
class Meta(type):
def __new__(cls, name, parents, namespace):
namespace['parameters'] = {
**deepcopy(parents[0].parameters),
**namespace['parameters']
}
return super().__new__(cls, name, parents, namespace)
class MiddleClass(Baseclass, metaclass=Meta):
parameters = {
'example_param2': ParamObject(name='example_param2', editable=False),
}
例如,这当然是一个不处理多个父类的简化版本。
您可以使用元类,例如建议的其他答案,但我不确定新程序员理解起来有多容易。
您可以通过在 class 上调用__bases__
来访问 class 继承的类。遗憾的是,在 python 上,您无法引用在 class 主体上创建的 class,这意味着您不能执行以下操作:
class A:
bases = A.__bases__ # Invalid code, A is not defined yet
如果你想这样做,同时保持参数 static,你可以在 class 定义之后这样做,它会有你正在寻找的确切行为,虽然有点难看:
class BaseClass:
parameters = {
'example_param1': ParamObject(name='example_param1', editable=True),
}
class MiddleClass(Baseclass):
pass
MidleClass.parameters = {
**deepcopy(MidleClass.__bases__[0].parameters),
'example_param2': ParamObject(name='example_param2', editable=False),
}
现在,稍微改进一下,如果你的parameters
真的总是一个'Dict[str, object]',你不需要做一个深层复制,因为使用**
以功能方式起作用。 您还可以使用__bases__
值处理多个父类,以确保捕获每个值。 所以,如果我要这样做,我会做这样的事情:
def base_parameters(cls):
parameters = {}
for base in cls.__bases__:
parameters.update(base.parameters)
return parameters
class BaseClass:
parameters = {
'example_param1': ParamObject(name='example_param1', editable=True),
}
class MiddleClass(BaseClass):
pass
MiddleClass.parameters = {
**base_parameters(MiddleClass),
'example_param2': ParamObject(name='example_param2', editable=False),
}
class ChildClass(MiddleClass):
pass
ChildClass.parameters = {
**base_parameters(ChildClass),
'example_param3': ParamObject(name='example_param3', editable=True),
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.