我正在实现enum class,并且想要检索有关enum成员的汇总信息。每个enum代表一个具有不同引脚数的分线板,我希望在所有板上获得最大的引脚数。我的方法是添加一个类属性_max_pins,该属性在每个成员的__init__期间进行调整。

问题是,如果成员也将成为成员,则不可能提前定义_max_pins。在成员之后定义它无济于事,因为成员在其__init__期间无法访问它
我看过Declare a static variable in an enum class,但是可以在__init__之后建立表-可以这样做,但是初始化后需要再次扫描所有成员。

class IgelTyp(Enum):
    LED_1 = (24, 1)
    LED_2 = (24, 2)
    LED_3 = (16, 4)

    _max_pin = -1

    def __init__(self, pins, groups):
        if _max_pin < pins//groups:     # gives error
            _max_pin = pins//groups

    @classmethod
    def get_max_pins(cls):
        return cls._max_pin


上面的代码产生UnboundLocalError: local variable '_max_pin' referenced before assignment

当我将_max_pin的分配移到成员定义的前面时,它告诉我TypeError: __init__() missing 2 required positional arguments: ...

编辑1
实际上,无论我将作业放在班级中的什么位置,都会引发TypeError
当我使用IgelTyp._max_pin = -1时,我得到一个NameError: name 'IgelTyp' is not defined

任何人都有有效且易读的解决方案?

最佳答案

一次性解决方案:

更改您的__init__以直接访问该类的字典:

def __init__(self, pins, groups):
    max_pin = self.__class__.__dict__.get('max_pin', 0)
    self.__class__.max_pin = max(max_pin, pins//groups)


有趣的是,您可以通过在max_pin的末尾添加以下行来轻松地使每个LED成员存储自己的__init__

    self.max_pin = pins//groups


所以:

>>> IgelTyp.max_pin
24


但:

>>> IgelType.LED_2.max_pin
12






可重复使用的解决方案

创建您自己的类属性描述符,并使用它来防止max_pin成为IgelTyp成员:

class ClassVar:              # add (object) if using Python 2
    "a class variable"

    def __init__(self, value):
        # store initial value
        self.value = value

    def __get__(self, *args):
        # get value in ClassVar instance (only doable because all instances
        # share same value)
        return self.value

    def __set__(self, _, value):
        # save value in ClassVar instance (only doable because all instances
        # share same value)
        self.value = value


描述符(例如property)通常将值存储在实例本身上,以便每个实例可以拥有自己的值(例如,示例中的24、12和4);但是,由于您想知道所有实例的最大引脚数,因此我们只将单个值保存在ClassVar实例上。

IgelTyp的更改:

class IgelTyp(Enum):

    LED_1 = (24, 1)
    LED_2 = (24, 2)
    LED_3 = (16, 4)

    max_pin = ClassVar(0)

    def __init__(self, pins, groups):
        self.max_pin = max(self.max_pin, pins//groups)


并在使用中:

>>> IgelTyp.max_pin
24
>>> IgelTyp.LED_2.max_pin
24

10-04 20:43