I find myself writing this class often in my python code when I need a quick single use class.
class Struct(object):
def __init__( self, **kwargs ):
for k in kwargs:
setattr(self,k,kwargs[k])
The basic idea is so I can do quick things like this:
foo = Struct( bar='one', baz=1 )
print foo.bar
foo.baz += 1
foo.novo = 42 # I don't do this as often.
Of course this doesn't scale well and adding methods is just insane, but even so I have enough data-only throw-away classes that I keep using it.
This is what I thought namedtuple was going to be. But the namedtuple's syntax is large and unwieldy.
Is there something in the standard library I haven't found yet that does this as well or better?
Is this bad bad style? or does it have some hidden flaw?
Two concrete example to show why I don't just use a dict. Both of these examples could be done with a dict but it obviously non-idiomatic.
#I know an order preserving dict would be better but they don't exist in 2.6.
closure = Struct(count=0)
def mk_Foo( name, path ):
closure.count += 1
return (name, Foo( name, path, closure.count ))
d = dict([
mk_Foo( 'a', 'abc' ),
mk_Foo( 'b', 'def' ),
# 20 or so more
] )
@contextmanager
def deleter( path ):
control = Struct(delete=True,path=path)
try:
yield control
finally:
if control.delete:
shutil.rmtree(path)
with deleter( tempfile.mkdtemp() ) as tmp:
# do stuff with tmp.path
# most contexts don't modify the delete member
# but occasionally it's needed
if keep_tmp_dir:
tmp.delete = False
NamedTuple: The NamedTuple is a class that contains the data like a dictionary format stored under the 'collections' module. It stored the data in a key-value format where each key having mapped to more values.
Python namedtuple is an immutable container type, whose values can be accessed with indexes and named attributes. It has functionality like tuples with additional features. A named tuple is created with the collections. namedtuple factory function.
Tuples are immutable, whether named or not. namedtuple only makes the access more convenient, by using names instead of indices. You can only use valid identifiers for namedtuple , it doesn't perform any hashing — it generates a new type instead.
Data classes advantages over NamedTuplemutable objects. inheritance support. property decorators, manageable attributes. generated method definitions out of the box or customizable method definitions.
From Python 3.3 and afterwards, you can use types.SimpleNamespace:
>>> import types
>>> foo = types.SimpleNamespace(bar='one', baz=1)
>>> print(foo.bar)
one
>>> foo.baz += 1
>>> foo.novo = 42
The builtin type is roughly equivalent to the following code:
class SimpleNamespace:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __repr__(self):
keys = sorted(self.__dict__)
items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
return "{}({})".format(type(self).__name__, ", ".join(items))
def __eq__(self, other):
return self.__dict__ == other.__dict__
update
Starting with Python 3.7, you can use the dataclass module:
from dataclasses import dataclass, field
@dataclass
class Struct:
bar: str = field(default='one')
baz: int = field(default=1)
You can use this as follows:
foo = Struct( bar='one', baz=1 )
print(foo.bar)
foo.baz += 1
foo.novo = 42
By default, it incorporates equality testing and a nice looking repr:
>>> foo == Struct(bar='one', baz=2)
True
>>> foo
Struct(bar='one', baz=2)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With