tags:

views:

108

answers:

3

I can use this when I need multiple objects with different attributes:

class struct(object):
   def __init__(self,*args,**kwargs):
      for key,val in kwargs.items():
         setattr(self,key,val)

But I'm wondering if there isn't a built-in already?

+9  A: 

Unless I'm not understanding your question, isn't this what we use a dict for? Sure, it's notationally slightly different, but an object's attributes are internally still stored in a dict (namely __dict__). It's a matter of notation.

But, if you insist, then this is one way to do it:

>>> class struct(dict):
...     def __getattribute__(self, key):
...         return self[key]
... 
>>> s = struct(a=5, b=7)
>>> s.a
5

Note I'm using __getattribute__ instead of __getattr__. The reason for this, is that otherwise we cannot store attributes with names such as get and keys, since these are methods defined by dict.

The solution by SilentGhost is probably more efficient and works just as well, without resorting to the use of __getattribute__. The code then becomes:

>>> def struct(**kwargs):
...     return type('Struct', (object,), kwargs)
... 
>>> s = struct(a=5, b=7)
>>> s.a
5
Stephan202
+3  A: 

I'm not certain why you're not using a dictionary for this.

x = {}
x.update([(1, 2), (3, 4), (5, 6)])
print x

result

{1: 2, 3: 4, 5: 6}

or

x.update(a=2, b=4, c=6)

results in

{'a': 2, 'c': 6, 'b': 4}
Bryan McLemore
+2  A: 

I have wondered the same thing. I enjoy the convenience of x.foo instead of x["foo"]; a single period is far easier to type (and get correct) than all of [""].

The advantage of a dict is that anything can be a key. (Well, anything hashable.) But when I have a bunch of values I want to just bundle together, the key names I pick are valid identifiers anyway.

Here's the basic version of this idea:

class struct(object):
    pass

x = struct()
x.foo = 1

As long as you are going to this much trouble, you might as well add the __init__() that handles kwargs for convenient initialization. But I'm lazy and I was hoping for something built-in.

I tried this, which doesn't work:

x = object()
x.foo = 1   # raises AttributeError exception

I asked about it, and the answer I got was that object is the root of all types in Python; it is as small as possible. If it could act like a class instance, with its own __dict__ attribute, then every object ever created in Python would need an attached __dict__.

I would have liked to see struct added as a built-in for Python 3.x. But I understand why it was not: keeping the language small and clean is a worthy goal, and this feature is trivially easy to code up yourself.

steveha
Nice analysis. Let me add two things: (1) this property of `object`, that it doesn't have `__dict__`, can also be had for other classes, by defining `__slots__` (see http://docs.python.org/reference/datamodel.html#slots for more); (2) with respect to your last paragraph: `import this` states: *There should be one-- and preferably only one --obvious way to do it.*
Stephan202