27

Sometimes I need to create an anonymous class instance in python, just like c#:

var o = new {attr1="something", attr2=344};

but in python I do it in this way:

class Dummy: pass
o = Dummy()
o.attr1 = 'something'
o.attr2 = 344
# EDIT 1
print o.attr1, o.attr2

how can I do that in a Pythonic way and a single statement?

4
  • 2
    I wouldn't use a class as just a container object. Use a named tuple or a dictionary. What are you trying to accomplish with these classes? Commented Dec 15, 2012 at 23:37
  • @Blender: named tuples need to be defined firstly, then make instance of it. i need single statement(the pythonic way) Commented Dec 15, 2012 at 23:42
  • 1
    What are you using these classes for? Do they have methods or are they just containers? If they're containers, use a container object, not a class. Commented Dec 15, 2012 at 23:43
  • Possible duplicate of Does Python have anonymous classes? Commented Mar 31, 2019 at 2:18

6 Answers 6

38
o = type('Dummy', (object,), { "attr1": "somehing", "attr2": 344 })
o.attr3 = "test"
print o.attr1, o.attr2, o.attr3
Sign up to request clarification or add additional context in comments.

3 Comments

@pylover, the pythonic way would really be a dict, this is a hack.
@pylover @rid I don't want to get bizantine but an AttrBunch-like type that is essentially a dict with attribute access will fit the bill with arguably nicer syntax and without offending the python arbiters of good taste. What seems to me very unpythonic and unnecesary here is the creation of an ad hoc type. It's not that python is all for a class-less society, but that it likes classes when you have some predefined, conceptual structure in mind, not for a random bunch of attributes, even less if the class is dynamically created.
What happens when you try to create a different "type" with the same name? Is it allowed? I wonder how the easydict package work (It's a package that makes you feel like JS - you give it a JSON string and you get objects accessible using real fields instead of dictionary keys)
15

If you are using Python 3.3 or later, you can use types.SimpleNamespace:

from types import SimpleNamespace

o = SimpleNamespace(attr1="something", attr2=344)
print(o)

# namespace(attr1='something', attr2=344)

Comments

9

type

while this is not precisely a single statement I think creating a wrapper around the magic of the accepted answer makes it by far more readable.

import inspect 

# wrap the type call around a function 
# use kwargs to allow named function arguments
def create_type(name, **kwargs):
    return type(name, (object,), kwargs)

# example call to make a structure
p = create_type('foobar', xxx='barfoo', seti=0)

assert p.xxx == 'barfoo'
assert p.seti == 0

print inspect.getmembers(p)

Output

[('__class__', <type 'type'>),
 ('__delattr__', <slot wrapper '__delattr__' of 'object' objects>),
 ('__dict__', <dictproxy object at 0x9a5050>),
 ('__doc__', None),
 ('__format__', <method '__format__' of 'object' objects>),
 ('__getattribute__', <slot wrapper '__getattribute__' of 'object' objects>),
 ('__hash__', <slot wrapper '__hash__' of 'object' objects>),
 ('__init__', <slot wrapper '__init__' of 'object' objects>),
 ('__module__', '__main__'),
 ('__new__', <built-in method __new__ of type object at 0x399c578460>),
 ('__reduce__', <method '__reduce__' of 'object' objects>),
 ('__reduce_ex__', <method '__reduce_ex__' of 'object' objects>),
 ('__repr__', <slot wrapper '__repr__' of 'object' objects>),
 ('__setattr__', <slot wrapper '__setattr__' of 'object' objects>),
 ('__sizeof__', <method '__sizeof__' of 'object' objects>),
 ('__str__', <slot wrapper '__str__' of 'object' objects>),
 ('__subclasshook__', <built-in method __subclasshook__ of type object at 0x919370>),
 ('__weakref__', <attribute '__weakref__' of 'foobar' objects>),
 # here they are
 ('seti', 0),
 ('xxx', 'barfoo')]

namedtuple

from collections import namedtuple

d = { 'a' : 'foo', 'b' : 'bar' }
foobar = namedtuple('foobar', d.keys())(**d)
print foobar

Output

Python 2.7.5 (default, May 30 2013, 16:55:57) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from collections import namedtuple
>>> d  =  { 'a' : 'foo', 'b' : 'bar' }
>>> foobar = namedtuple('foobar', d.keys())(**d)
>>> print foobar
foobar(a='foo', b='bar')
>>> 

1 Comment

@pylover: if the type is used more often and consistently it seems named tuples are preferable. See also: stackoverflow.com/questions/2970608/…
2
class attrdict(dict):
    def __getattr__(self, key):
        return self[key]

o = attrdict(attr1='something', attr2=344)

o.attr1

But it seems like you should probably just use a standard dict.

3 Comments

i cannot set attr on this kind of object just like a class instance, i.e: o.attr3 = 345.
@pylover: Override __setitem__.
@mwhite: Don't you mean __getattr__ (and __setattr__) rather than __getitem__?
1

For an anonymous object you need a type that supports __get/set attr__() for any token. There are several choices, but I think the most readable is lambda. For example,

o = lambda: None
o.attr1 = 'something'
o.attr2 = 344
print(o.attr1, o.attr2)

You can easily convert it into a dict

d = vars(o)
print(d)
for k,v in d.items():
    print(k,'=',v)
# convert it to json...
s = json.dumps(d)
print(s)

You might say "WTF is it a function?" well, yes, it is a function. You can call it

o()

and nothing happens. It just returns None, which is harmless and not really the point.

I don't see very many people using lambda:None to create anonymous objects, so perhaps it isn't yet "pythonic" but if more of us start using it, then it will become so.

Comments

0

I prefer the dict answer from mwhite, but here's how I've done it in the past using the "magic" of kwargs (pun intended).

class ObjectFromDict(object):
    def __init__(**kwargs):
        for k in kwargs:
            if k not in self.__dict__:
                setattr(k,v)

myObj = ObjectFromDict(**{'foo': 'bar', 'baz': 'monkey'})
print myObj.foo #bar

2 Comments

i using this solution for many years, but it needs to define a class , then instantiate it.
Did you really run this code? I see no self argument, no v being defined, 2 arguments in setattr...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.