Joe*_*son 7 python inheritance
我在python中有大量的自动生成的类,它们实际上代表了部分通信协议的枚举,它们看起来像这样
# definitions.py
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
class AlpacaType(ParamEnum):
Fuzzy = 0
ReallyMean = 1
# etc etc etc
Run Code Online (Sandbox Code Playgroud)
以这种方式定义事物使得自动发生器和人类都可以轻松修改.ParamEnum类提供来自传入网络数据等的所有功能,获取/设置,比较,转换和创建.
但是,这些类需要一些额外的元数据.我不希望添加这个到每个类别中的源定义,虽然,因为它使得它的可读性和将打破自动发生器
目前我正在这样做
# param_enum.py
class ParamEnum(object):
def __init__(self):
self.__class__._metadata = get_class_metadata(self.__class__)
Run Code Online (Sandbox Code Playgroud)
然而,这对我来说有点低效,因为每次我们实例化其中一个枚举(经常发生)时都会发生这种情况,而不仅仅是定义(元数据不会改变,所以它只需要设置一次)
我尝试将其添加到定义文件的底部,但也遇到了问题.
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
Run Code Online (Sandbox Code Playgroud)
在定义类时,是否有一种方法在python中覆盖/添加功能,可以继承到子类?理想情况下,我喜欢这样的东西
class ParamEnum(object):
def __when_class_defined__(cls):
add_metadata(cls)
Run Code Online (Sandbox Code Playgroud)
使用类装饰器
def add_metadata(cls):
cls._metadata = get_class_metadata(cls)
return cls
@add_metadata
class StatusCodes(ParamEnum):
Success = 1
Error = 2
UnexpectedAlpaca = 3
Run Code Online (Sandbox Code Playgroud)
你想要做的事实上是拥有装饰器的动机:在创建类或函数之后对其进行修改.
如果您不熟悉装饰器,请阅读此内容(虽然它有点冗长).
您也可以使用元类,但它们比装饰器引入更多复杂性.如果你想避免额外的装饰线,@add_metadata并且你认为它对于指定的子类来说是多余的ParamEnum,你也可以在基类中创建_metadata 一个具有延迟评估的描述符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()
Run Code Online (Sandbox Code Playgroud)