This looks like a mutable version of 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'