简体   繁体   English

你可以动态地将类属性/变量添加到 python 中的子类吗?

[英]Can you dynamically add class attributes/variables to a subclass in python?

I have a large amount of auto-generated classes in python that essentially represent enums for part of a communication protocol, they look like so我在 python 中有大量自动生成的类,它们基本上代表通信协议的一部分的枚举,它们看起来像这样

# definitions.py

class StatusCodes(ParamEnum):
    Success = 1
    Error = 2
    UnexpectedAlpaca = 3

class AlpacaType(ParamEnum):
    Fuzzy = 0
    ReallyMean = 1

# etc etc etc

Defining things this way makes it easy for the auto-generator and also for humans to modify.以这种方式定义事物使自动生成器和人类更容易修改。 The ParamEnum class provides all the functionality, get/setting, comparison, conversion and creation from the incoming network data and etc. ParamEnum 类提供所有功能、获取/设置、比较、转换和从传入网络数据创建等。

However, these classes require some extra meta-data.但是,这些类需要一些额外的元数据。 I do not want to add this into the source definition of each class though, as it makes it less readable and will break the autogenerator希望添加这个到每个类,但是源定义,因为它使得它的可读性和将打破自动发生器

At the moment I am doing it like this目前我正在这样做

# param_enum.py

class ParamEnum(object):
    def __init__(self):
        self.__class__._metadata = get_class_metadata(self.__class__)

however that strikes me as somewhat inefficient, since this will happen every time we instantiate one of these Enums (which happens often), not just on definition (the metadata does not change, so it only needs to be set once)然而这让我觉得有些低效,因为每次我们实例化这些枚举之一时都会发生这种情况(经常发生),而不仅仅是定义(元数据不会改变,所以它只需要设置一次)

I tried added this to the bottom of the definition file, but ran into problems there too.我尝试将其添加到定义文件的底部,但在那里也遇到了问题。

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

Is there a way in python of overriding/adding functionality to when the class is defined, that can be inherited to subclasses? python中有没有办法在定义类时覆盖/添加功能,可以继承到子类? Ideally I'd like something like理想情况下,我想要类似的东西

class ParamEnum(object):
    def __when_class_defined__(cls):
        add_metadata(cls)

Use a class decorator使用类装饰器

def add_metadata(cls):
    cls._metadata = get_class_metadata(cls)
    return cls

@add_metadata
class StatusCodes(ParamEnum):
    Success = 1
    Error = 2
    UnexpectedAlpaca = 3

What you want to do is in fact the very motivation to have decorators: The modification of a class or function after it has been created.实际上,您想要做的正是拥有装饰器的动机:在创建类或函数后对其进行修改。

If you are unfamiliar with decorators, please read this (although it's a bit lengthy).如果您不熟悉装饰器,请阅读本文(虽然有点冗长)。

You could also use metaclasses, but they introduce more complexity than a decorator.您也可以使用元类,但它们比装饰器引入了更多的复杂性。 If you want to avoid the additional decoration line @add_metadata and you think it is redundant with respect to the specified subclass ParamEnum , you could also make _metadata a descriptor with lazy evaluation within the base class ParamEnum .如果您想避免额外的修饰行@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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM