有没有办法从 class 作用域引用 object 的基础 __class__?
Is there a way to reference an object's base __class__ from class scope?
我有一系列 classes,继承自几个可能的 parents 中的一个,它们都共享一个基础 class。每个 class 都有一个 class-scope Dict[str, object] parameters
是基于 class 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),
行不令人满意。随着时间的推移,这些 child class 将由对编码只有基本了解的人进行编辑,因此我想让代码尽可能简单 cut-and-pasteable。
有什么我可以在 class 范围内调用以获得 super().__class__
的等价物吗?我希望用户能够将基数 class 从 MiddleClass
更改为 MiddleClass2
,而无需记住在多个位置更改基数 class。
如果您的 class 仅继承自一个 class,您可以使用 metaclass:
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),
}
这当然是一个简化的版本,例如不处理多个父 classes。
你可以用元class来做到这一点。检查继承树中的所有 classes 以查看它们是否具有 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'}
您可以使用 __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),
}
您可以使用 Metaclasses,例如建议的其他答案,但我不确定这对新程序员来说有多容易理解。
您可以通过在 class 上调用 __bases__
来访问 class 继承自的 classes。遗憾的是,在 python 上你不能引用你在 class 主体上创建的 class,这意味着你不能这样做:
class A:
bases = A.__bases__ # Invalid code, A is not defined yet
如果你想这样做,同时保持参数静态,你可以在 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__
值处理多个父 classes,以确保捕获每个值。所以,如果我要这样做,我会这样做:
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),
}
我有一系列 classes,继承自几个可能的 parents 中的一个,它们都共享一个基础 class。每个 class 都有一个 class-scope Dict[str, object] parameters
是基于 class 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),
行不令人满意。随着时间的推移,这些 child class 将由对编码只有基本了解的人进行编辑,因此我想让代码尽可能简单 cut-and-pasteable。
有什么我可以在 class 范围内调用以获得 super().__class__
的等价物吗?我希望用户能够将基数 class 从 MiddleClass
更改为 MiddleClass2
,而无需记住在多个位置更改基数 class。
如果您的 class 仅继承自一个 class,您可以使用 metaclass:
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),
}
这当然是一个简化的版本,例如不处理多个父 classes。
你可以用元class来做到这一点。检查继承树中的所有 classes 以查看它们是否具有 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'}
您可以使用 __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),
}
您可以使用 Metaclasses,例如建议的其他答案,但我不确定这对新程序员来说有多容易理解。
您可以通过在 class 上调用 __bases__
来访问 class 继承自的 classes。遗憾的是,在 python 上你不能引用你在 class 主体上创建的 class,这意味着你不能这样做:
class A:
bases = A.__bases__ # Invalid code, A is not defined yet
如果你想这样做,同时保持参数静态,你可以在 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__
值处理多个父 classes,以确保捕获每个值。所以,如果我要这样做,我会这样做:
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),
}