Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Namedtuple like class

Tags:

python

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?

update

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
  
like image 658
deft_code Avatar asked Feb 27 '11 02:02

deft_code


People also ask

Is a Namedtuple a class?

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.

What type is a Namedtuple?

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.

What is difference between Namedtuple and tuple?

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.

What is one advantage of classes over Namedtuple?

Data classes advantages over NamedTuplemutable objects. inheritance support. property decorators, manageable attributes. generated method definitions out of the box or customizable method definitions.


1 Answers

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)
like image 149
Raymond Hettinger Avatar answered Oct 17 '22 08:10

Raymond Hettinger