26

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?

pylover
  • 7,670
  • 8
  • 51
  • 73
  • 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? – Blender Dec 15 '12 at 23:37
  • @Blender: named tuples need to be defined firstly, then make instance of it. i need single statement(the pythonic way) – pylover Dec 15 '12 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. – Blender Dec 15 '12 at 23:43
  • Possible duplicate of [Does Python have anonymous classes?](https://stackoverflow.com/questions/1123000/does-python-have-anonymous-classes) – Anderson Green Mar 31 '19 at 02:18

5 Answers5

37
o = type('Dummy', (object,), { "attr1": "somehing", "attr2": 344 })
o.attr3 = "test"
print o.attr1, o.attr2, o.attr3
rid
  • 61,078
  • 31
  • 152
  • 193
  • 6
    @pylover, the pythonic way would really be a `dict`, this is a hack. – rid Dec 15 '12 at 23:47
  • 1
    @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. – memeplex Mar 08 '16 at 18:54
  • 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) – SomethingSomething Dec 21 '16 at 13:39
11

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)
Elias Zamaria
  • 96,623
  • 33
  • 114
  • 148
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')
>>> 
Alexander Oh
  • 24,223
  • 14
  • 73
  • 76
  • 1
    @pylover: if the type is used more often and consistently it seems named tuples are preferable. See also: http://stackoverflow.com/questions/2970608/what-are-named-tuples-in-python – Alexander Oh Feb 11 '14 at 10:16
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.

mwhite
  • 2,041
  • 1
  • 16
  • 21
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
bitcycle
  • 7,632
  • 16
  • 70
  • 121
  • i using this solution for many years, but it needs to define a class , then instantiate it. – pylover Dec 15 '12 at 23:47
  • 3
    Did you really run this code? I see no `self` argument, no `v` being defined, 2 arguments in `setattr`... – tokland Oct 20 '14 at 12:34