11# enum.py
2- # version="1.2.3 "
2+ # version="1.2.4 "
33
44
55class EnumValue :
@@ -11,9 +11,6 @@ def __init__(self, value, name):
1111 def __repr__ (self ):
1212 return f"{ self .name } : { self .value } "
1313
14- # def __str__(self):
15- # return str(self.value)
16-
1714 def __call__ (self ):
1815 return self .value
1916
@@ -22,9 +19,6 @@ def __eq__(self, other):
2219 return self .value == other .value
2320 return self .value == other
2421
25- # def __int__(self):
26- # return self.value
27-
2822 def __setattr__ (self , key , value ):
2923 raise AttributeError ("EnumValue is immutable" )
3024
@@ -40,6 +34,9 @@ def __new__(cls, name=None, names=None):
4034 return super (Enum , cls ).__new__ (cls )
4135
4236 def __init__ (self , name = None , names = None ):
37+ if hasattr (self , '_initialized' ):
38+ return
39+
4340 # 1. Convert class-level attributes (constants) to EnumValue objects
4441 self ._scan_class_attrs ()
4542
@@ -64,29 +61,49 @@ def _lookup(cls, value):
6461 if not callable (attr ) and attr == value :
6562 # Wrap static numbers found in class definition
6663 return EnumValue (attr , key )
67-
6864 raise AttributeError (f"{ value } is not in { cls .__name__ } " )
6965
70- def list (self ):
66+ @classmethod
67+ def __iter__ (cls ):
68+ if '_initialized' not in cls .__dict__ :
69+ cls ._scan_class_attrs ()
70+ setattr (cls , '_initialized' , True )
71+
72+ for key in dir (cls ):
73+ if key .startswith ('_' ):
74+ continue
75+ attr = getattr (cls , key )
76+ if isinstance (attr , EnumValue ):
77+ yield attr
78+
79+ @classmethod
80+ def list (cls ):
81+ if '_initialized' not in cls .__dict__ :
82+ cls ._scan_class_attrs ()
83+ setattr (cls , '_initialized' , True )
84+
7185 # Returns a list of all members
72- return [member for member in self ]
86+ return [getattr (cls , key ) for key in dir (cls )
87+ if isinstance (getattr (cls , key ), EnumValue )]
7388
74- def _update (self , key , value ):
75- setattr (self .__class__ , key , EnumValue (value , key ))
89+ @classmethod
90+ def _update (cls , key , value ):
91+ setattr (cls , key , EnumValue (value , key ))
7692
77- def _scan_class_attrs (self ):
93+ @classmethod
94+ def _scan_class_attrs (cls ):
7895 # Converts static class attributes into EnumValue objects
7996 # List of methods and internal names that should not be converted
8097 ignored = ('is_value' , 'list' )
81- for key in dir (self . __class__ ):
98+ for key in dir (cls ):
8299 # Skip internal names and methods
83100 if key .startswith ('_' ) or key in ignored :
84101 continue
85102
86- value = getattr (self . __class__ , key )
103+ value = getattr (cls , key )
87104 # Convert only constants, not methods
88105 if not callable (value ) and not isinstance (value , EnumValue ):
89- self ._update (key , value )
106+ cls ._update (key , value )
90107
91108 def is_value (self , value ):
92109 return any (member .value == value for member in self )
@@ -100,8 +117,11 @@ def __repr__(self):
100117 return f"{ self .__class__ .__name__ } (names={ members } )"
101118
102119 def __call__ (self , value ):
120+ if '_initialized' not in self .__class__ .__dict__ :
121+ self ._scan_class_attrs ()
122+ object .__setattr__ (self .__class__ , '_initialized' , True )
103123 for member in self :
104- if member .value == value :
124+ if member .value == value or member . name == value :
105125 return member
106126 raise AttributeError (f"{ value } is not in { self .__class__ .__name__ } " )
107127
@@ -118,12 +138,6 @@ def __delattr__(self, key):
118138 def __len__ (self ):
119139 return sum (1 for _ in self )
120140
121- def __iter__ (self ):
122- for key in dir (self .__class__ ):
123- attr = getattr (self .__class__ , key )
124- if isinstance (attr , EnumValue ):
125- yield attr
126-
127141 def __eq__ (self , other ):
128142 if not isinstance (other , Enum ):
129143 return False
@@ -134,28 +148,36 @@ def __eq__(self, other):
134148 # --- Usage Example 1 ---
135149 # Standard Class Definition
136150 class Color (Enum ):
137- RED = 'red'
138- GREEN = 'green'
139-
151+ RED = 1
152+ GREEN = 2
153+ BLUE = 3
154+
155+ print ("Color.list():" , Color .list ())
156+ print ("Color().list():" , Color ().list ())
157+
158+ # Iteration
159+ print ("Members list:" , [member for member in Color ()])
160+ print ("Names list:" , [member .name for member in Color ()])
161+ print ("Values list:" , [member .value for member in Color ()])
162+
140163 # Create instance
141164 c = Color ()
142165 print (f"Enum c: { c } " )
143- print ("c.list():" , c .list ())
144166
145167 # Basic access
146168 print (f"RED: Name={ c .RED .name } , Value={ c .RED .value } , EnumValue={ c .RED } , Call={ c .RED ()} " )
147169
148170 # Assertions
149171 assert c .RED .name == 'RED'
150- assert c .RED .value == 'red'
151- assert c .RED == 'red'
152- assert c .RED () == 'red'
172+ assert c .RED .value == 1
173+ assert c .RED == 1
174+ assert c .RED () == 1
153175
154176 # Reverse Lookup via instance call
155- print (f"c('red' ) lookup object: { c ('red' )} , Name={ c ('red' ).name } , value={ c ('red' ).value } " ) # RED
156- assert c ('red' ).name == 'RED'
157- assert c ('red' ).value == 'red'
158- assert c ('red' ) == 'red'
177+ # print(f"c(1 ) lookup object: {c(1 )}, Name={c(1 ).name}, value={c(1 ).value}") # RED
178+ assert c (1 ).name == 'RED'
179+ assert c (1 ).value == 1
180+ assert c (1 ) == 1
159181
160182 # Iteration
161183 print ("Values list:" , [member .value for member in c ])
0 commit comments