tags:

views:

100

answers:

6

Quite often, I find myself wanting a simple, "dump" object in Python which behaves like a JavaScript object (ie, its members can be accessed either with .member or with ['member']).

Usually I'll just stick this at the top of the .py:

class DumbObject(dict):
    def __getattr__(self, attr):
        return self[attr]
    def __stattr__(self, attr, value):
        self[attr] = value

But that's kind of lame, and there is at least one bug with that implementation (although I can't remember what it is).

So, is there something similar in the standard library?

And, for the record, simply instanciating object doesn't work:

>>> obj = object()
>>> obj.airspeed = 42
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'object' object has no attribute 'airspeed'

Edit: (dang, should have seen this one coming)… Don't worry! I'm not trying to write JavaScript in Python. The place I most often find I want this is while I'm still experimenting: I have a collection of "stuff" that doesn't quite feel right to put in a dictionary, but also doesn't feel right to have its own class.

+4  A: 

There is no "standard library" with that kind of object, but on ActiveState there is a quite well-known recipe from Alex Martelli, called "bunch".

Note: there's also a package available on pypi called bunch and that should do about the same thing, but I do not know anything about its implementation and quality.

Roberto Liffredo
Good to know about - thanks.
David Wolever
+2  A: 

I'm not a big fan of that, because you get into the "what if you define 'keys'":

foo = DumbObject()
foo.moshe = 'here'
foo.keys # --> gives a callable, if you'll call it you'll get ['moshe']
foo.keys = 'front-door'
foo.keys # --> oh look, now it's a string 'front-door'

Is "keys" supposed to be a defined method on your object, or is that just happenstance? If it is, then you better define DumbObject as

class DumbObject(object):
    def __init__(self):
        self._dict = {}
    def __getitem__(self, key):
        return self._dict[key]
    __getattr__ = __getitem__
    # Ditto for set
def asDictionary(do):
    return do._dict

But why are you doing it? Are you sure that this is the right answer? Perhaps you should be using the right type of object?

moshez
Ah, I hadn't considered that. In that case, there are at least two bugs with the implementation I've used in the past :P
David Wolever
I often like it to experiment with - for data that doesn't really feel "right" in a dictionary, but formalizing it into a class feel overkill.
David Wolever
I think it's your feelings which are the problem -- "formalizing it into a class" is probably not an overkill. It feels like an overkill in languages where classes aren't, at a minimum, a mere "class Foo(object): pass" :-D
moshez
That is an interesting idea - simply using, eg, `class Foo: airspeed = 42` - I hadn't considered that. However, it does have the problem that it doesn't behave like a dictionary (yes, there is `__dict__`…), which makes experimentation more difficult.
David Wolever
A: 

You seem to be wanting to write JavaScript in Python, and that is as bad as writing Python in JavaScript, and nearly as bad as writing COBOL in Java.

That being said, it really depends on what you are trying to achieve. If what you want is to create an object from an iterable, you might be interested on the Named Tuple class.

Else, if you really need this functionality, you can use moshez' DumbObject, but as he said, you might be approaching this in a less than optimum way.

Python is not JavaScript, just as Python is not Java.

voyager
+2  A: 

You can try with attrdict:

class attrdict(dict):
    def __init__(self, *args, **kwargs):
        dict.__init__(self, *args, **kwargs)
        self.__dict__ = self

a = attrdict(x=1, y=2)
print a.x, a.y
print a['x'], a['y']

b = attrdict()
b.x, b.y  = 1, 2
print b.x, b.y
print b['x'], b['y']
ars
Should complete your example with, for example, `print b['x']`. To show that it supports both attribute access methods.
PreludeAndFugue
Good point, PreludeAndFugue. I updated the code. Thanks. :)
ars
Changing `__dict__`?! That's disgusting! But, at the same time, intriguing…
David Wolever
+3  A: 

You may be interested in collections.namedtuple

Satoru.Logic
+1  A: 

If I understand you correctly, you want an object where you can just dump attributes. If I am correct, all you would have to do is create an empty class. For example:

>>> class DumpObject: pass
... 
>>>#example of usage:
...
>>> a = DumpObject()
>>> a.airspeed = 420
>>> print a.airspeed
420

That's it

None
Close, but I'd also like to be able to treat it like a dict (I guess that wasn't entirely clear).
David Wolever