I'm implementing an enum
class
and want to retrieve an aggregate information about the enum
members. Each enum
represents a breakout board with different number of pins, and I want to get the maximum number of pins over all boards. My approach was to add a class attribute _max_pins which is adjusted during __init__
of each member.
Problem is, it is not possible to define _max_pins ahead if the members as it would become a member, too. It does not help to define it after the members as then the members cannot access it during their __init__
I've looked at Declare a static variable in an enum class but the table can be set up after __init__
- that would be possible but would need to scan again all members after their initialization.
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
Above code produces UnboundLocalError: local variable '_max_pin' referenced before assignment
When I move the assignment of _max_pin in front of the member definition it tells me that TypeError: __init__() missing 2 required positional arguments: ...
Edit 1 Actually, the TypeError
is raised regardless where I put the assignment within the class. And when I use IgelTyp._max_pin = -1
I get a NameError: name 'IgelTyp' is not defined
Anyone has an efficient and readable solution?
One-off solution:
Change your __init__
to directly access the class's dictionary:
def __init__(self, pins, groups):
max_pin = self.__class__.__dict__.get('max_pin', 0)
self.__class__.max_pin = max(max_pin, pins//groups)
Interestingly, you could easily have each LED member store its own max_pin
by adding this line at the end of __init__
:
self.max_pin = pins//groups
so:
>>> IgelTyp.max_pin
24
but:
>>> IgelType.LED_2.max_pin
12
Reusable solution
Create your own class attribute descriptor, and use that to shield max_pin
from becoming an IgelTyp
member:
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
Descriptors, such as property
usually store the value on the instance itself so that each instance can have it's own value (such as 24, 12, and 4 from your example); however, since you want to know the maximum number of pins across all instances, we just save that single value on the ClassVar
instance.
The changes to 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)
and in use:
>>> IgelTyp.max_pin
24
>>> IgelTyp.LED_2.max_pin
24
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.