Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python simple naked objects

Tags:

python

oop

What's the easiest way to create a naked object that I can assign attributes to?

The specific use case is: I'm doing various operations on a Django object instance, but sometimes the instance is None (there is on instance). In this case I'd like to create the simplest possible fake object such that I can assign values to its attributes (eg. myobject.foo = 'bar').

Basically I'm looking for the Python equivalent of this piece of Javascript:

myobject = {}
myobject.foo = 'bar'

I know I can use a mock object/library for this, but I'm hoping for a very simple solution (as simple as the Javascript above). Is there a way to create a naked object instance? Something like:

myobject = object()
myobject.foo = 'bar'
like image 311
Parand Avatar asked May 30 '12 20:05

Parand


4 Answers

You need to create a simple class first:

class Foo(object):
    pass

myobject = Foo()
myobject.foo = 'bar'

You can make it a one-liner like this:

myobject = type("Foo", (object,), {})()
myobject.foo = 'bar'

The call to type functions identically to the previous class statement.

If you want to be really minimal...

myobject = type("", (), {})()

The key is that the built-in types (such as list and object) don't support user-defined attributes, so you need to create a type using either a class statement or a call to the 3-parameter version of type.

like image 168
chepner Avatar answered Oct 31 '22 21:10

chepner


If you're using Python >= 3.3 you could always use SimpleNamespace; which is included in the Python types module.

SimpleNamespace is great because you also get a repr and equivalency testing for free; both of which might come in handy even for a minimalist object.

Translating the JavaScript in the OP’s question would look like:

from types import SimpleNamespace

myobject = SimpleNamespace() # myobject = {}
myobject.foo = 'bar'

You can also use keyword arguments when instantiating SimpleNamespace. These arguments will become attributes on the instantiated SimpleNamespace:

p = SimpleNamespace(name='gary')
p.age = 32
p # => namespace(age=32, name='gary')

So a quick and easy way to turn a dictionary into a SimpleNamespace object —provided the dictionary keys are proper identifiers— is as simple as:

d = {
    'name': 'gary',
    'age': 33 # had a birthday. 
}
p = SimpleNamespace(**d)

Python >= 3.7 has dataclasses which are basically “mutable named tuples”. This could be something you may want to use if you have a lot of data objects.

like image 43
inazuma Avatar answered Oct 31 '22 19:10

inazuma


Use the Bunch module:

sudo pip install bunch

A bunch is a dictionary that allows to access its content via the dict.key syntax.

And then like that:

from bunch import Bunch
b = Bunch()
b.foo = "Bar"


b["foo2"] = "Bar2"
print b
>> Bunch(foo='Bar', foo2='Bar2')
b["foo"] = "Baz"
print b
>> Bunch(foo='Baz', foo2='Bar2')
like image 7
Qlaus Avatar answered Oct 31 '22 20:10

Qlaus


class NakedObject(object):
    pass

myobject = NakedObject()
myobject.foo = 'bar'
like image 4
Christian Witts Avatar answered Oct 31 '22 20:10

Christian Witts