你能动态添加 class attributes/variables 到 python 中的子 class 吗?
Can you dynamically add class attributes/variables to a subclass in python?
我在 python 中有大量自动生成的 classes,它们本质上代表了通信协议的一部分的枚举,它们看起来像这样
# definitions.py
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
class AlpacaType(ParamEnum):
Fuzzy = 0
ReallyMean = 1
# etc etc etc
以这种方式定义事物使得自动生成器和人类修改变得容易。 ParamEnum class 提供所有功能,get/setting,比较,转换和从传入网络数据创建等
但是,这些 classes 需要一些额外的元数据。不过,我 不想 想将它添加到每个 class 的源代码定义中,因为它会降低可读性并且会破坏自动生成器
目前我是这样做的
# param_enum.py
class ParamEnum(object):
def __init__(self):
self.__class__._metadata = get_class_metadata(self.__class__)
然而这让我觉得有点低效,因为每次我们实例化这些枚举之一时都会发生这种情况(经常发生),而不仅仅是定义(元数据不会改变,所以它只需要设置一次)
我尝试将其添加到定义文件的底部,但 运行 那里也出现了问题。
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
for var in locals(): # or globals?
add_metadata(var)
#doesn't work because it is in the same file, modifying dict while iteratng
在 python 的 overriding/adding 功能中有没有一种方法可以在定义 class 时继承给子 classes?理想情况下,我想要
class ParamEnum(object):
def __when_class_defined__(cls):
add_metadata(cls)
使用 class 装饰器
def add_metadata(cls):
cls._metadata = get_class_metadata(cls)
return cls
@add_metadata
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
你想做的其实就是拥有装饰器的动机:class 或函数创建后的修改。
如果您对装饰器不熟悉,请阅读this(虽然有点冗长)。
您也可以使用元classes,但它们比装饰器引入了更多的复杂性。如果你想避免额外的装饰线@add_metadata
并且你认为它相对于指定的subclassParamEnum
是多余的,你也可以使_metadata
a descriptor ] 在基础 class ParamEnum
.
内进行惰性评估
class MetadataDescriptor(object):
def __get__(self, obj, cls):
if cls._metadata_value is None:
cls._metadata_value = get_class_metadata(cls)
return cls._metadata_value
class ParamEnum(object):
_metadata_value = None
_metadata = MetadataDescriptor()
我在 python 中有大量自动生成的 classes,它们本质上代表了通信协议的一部分的枚举,它们看起来像这样
# definitions.py
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
class AlpacaType(ParamEnum):
Fuzzy = 0
ReallyMean = 1
# etc etc etc
以这种方式定义事物使得自动生成器和人类修改变得容易。 ParamEnum class 提供所有功能,get/setting,比较,转换和从传入网络数据创建等
但是,这些 classes 需要一些额外的元数据。不过,我 不想 想将它添加到每个 class 的源代码定义中,因为它会降低可读性并且会破坏自动生成器
目前我是这样做的
# param_enum.py
class ParamEnum(object):
def __init__(self):
self.__class__._metadata = get_class_metadata(self.__class__)
然而这让我觉得有点低效,因为每次我们实例化这些枚举之一时都会发生这种情况(经常发生),而不仅仅是定义(元数据不会改变,所以它只需要设置一次)
我尝试将其添加到定义文件的底部,但 运行 那里也出现了问题。
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
for var in locals(): # or globals?
add_metadata(var)
#doesn't work because it is in the same file, modifying dict while iteratng
在 python 的 overriding/adding 功能中有没有一种方法可以在定义 class 时继承给子 classes?理想情况下,我想要
class ParamEnum(object):
def __when_class_defined__(cls):
add_metadata(cls)
使用 class 装饰器
def add_metadata(cls):
cls._metadata = get_class_metadata(cls)
return cls
@add_metadata
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
你想做的其实就是拥有装饰器的动机:class 或函数创建后的修改。
如果您对装饰器不熟悉,请阅读this(虽然有点冗长)。
您也可以使用元classes,但它们比装饰器引入了更多的复杂性。如果你想避免额外的装饰线@add_metadata
并且你认为它相对于指定的subclassParamEnum
是多余的,你也可以使_metadata
a descriptor ] 在基础 class ParamEnum
.
class MetadataDescriptor(object):
def __get__(self, obj, cls):
if cls._metadata_value is None:
cls._metadata_value = get_class_metadata(cls)
return cls._metadata_value
class ParamEnum(object):
_metadata_value = None
_metadata = MetadataDescriptor()