patternpythonMinor
Struct in Python
Viewed 0 times
structpythonstackoverflow
Problem
I'm writing a struct class in Python and was wondering if this were a good way to write it:
and to initialize the object:
Also, is it actually worth using?
class Struct:
def __init__(self, **kwargs):
for key, value in kwargs.items():
if isinstance(getattr(self, key), str):
setattr(self, key, value)
def create(*args):
newStruct = type("Struct", (Struct,), {"__init__": Struct.__init__})
for arg in args:
setattr(newStruct, arg, str())
return newStructand to initialize the object:
myStruct = Struct.create('x', 'y')
variable = myStruct(x=2, y=4)Also, is it actually worth using?
Solution
This looks like a mutable version of
Following from your example (
The
Defaulting values to an empty string is weird; I'd expect the default values to be
It would be nice to have
Suggested implementation
Sample run:
namedtuple, with some oddities.Following from your example (
myStruct = Struct.create('x', 'y'); variable = myStruct(x=2, y=4)), I would expect variable.z to fail — and indeed it does raise an AttributeError: 'Struct' object has no attribute 'z'. I would also like to see variable.z = 5 fail with the same error, but it doesn't. So, if it doesn't enforce what members can be set, what's the point of this object? Why wouldn't I just use a regular dict?The
__init__ function looks like a constructor, such that I would be tempted to write myStruct = Struct('x', 'y') instead of myStruct = Struct.create('x', 'y')) — but it actually doesn't work that way. Also, I'd expect the constructor to work like namedtuple, accepting a typename, followed by field_names as either a list or a space-delimited string.Defaulting values to an empty string is weird; I'd expect the default values to be
None. You can initialize the dictionary using dict.fromkeys().It would be nice to have
__repr__() overridden, to make it easy to inspect the objects' contents for debugging.Suggested implementation
def Struct(typename, field_names):
class StructType:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
def __setattr__(self, key, value):
if hasattr(self, key):
super().__setattr__(key, value)
else:
getattr(self, key) # Trigger AttributeError
def __repr__(self):
return repr(self.__dict__)
return type(
typename,
(StructType,),
dict.fromkeys(field_names.split() if isinstance(field_names, str)
else field_names)
)Sample run:
>>> myStruct = Struct('myStruct', 'x y')
>>> variable = myStruct(x=2)
>>> variable
{'x': 2}
>>> variable.y
>>> variable.y = 4
>>> variable.y
4
>>> variable.z = 5
Traceback (most recent call last):
…
AttributeError: 'myStruct' object has no attribute 'z'
>>> variable.z
Traceback (most recent call last):
…
AttributeError: 'myStruct' object has no attribute 'z'Code Snippets
def Struct(typename, field_names):
class StructType:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
def __setattr__(self, key, value):
if hasattr(self, key):
super().__setattr__(key, value)
else:
getattr(self, key) # Trigger AttributeError
def __repr__(self):
return repr(self.__dict__)
return type(
typename,
(StructType,),
dict.fromkeys(field_names.split() if isinstance(field_names, str)
else field_names)
)>>> myStruct = Struct('myStruct', 'x y')
>>> variable = myStruct(x=2)
>>> variable
{'x': 2}
>>> variable.y
>>> variable.y = 4
>>> variable.y
4
>>> variable.z = 5
Traceback (most recent call last):
…
AttributeError: 'myStruct' object has no attribute 'z'
>>> variable.z
Traceback (most recent call last):
…
AttributeError: 'myStruct' object has no attribute 'z'Context
StackExchange Code Review Q#119848, answer score: 4
Revisions (0)
No revisions yet.