Python simple naked objects
Question:
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'
Answers:
Perhaps you are looking for something like this:
myobject={}
myobject['foo']='bar'
then it can be called like:
print myobject['foo']
or you could use a class object for this:
class holder(object):
pass
then you can use something like this:
hold=holder()
hold.myobject='bar'
print hold.myobject
You would need to subclass object first like this…
class Myobject(object):
pass
myobject1 = Myobject()
myobject1.foo = 'bar'
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
.
class NakedObject(object):
pass
myobject = NakedObject()
myobject.foo = 'bar'
You should probably just use a dict, as per @PsychicOak’s answer.
However, if you really want an object you can manipulate, try:
class FooClass(object): pass
You can then assign attributes on FooClass
itself, or on instances, as you wish.
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')
I usually prefer to create a null object for my class:
class User(Model):
username = CharField()
password = CharField()
NONE_USER = User(username='', password='')
Then I use it where I would use your naked object.
I’m coming here very late, but I’m surprised nobody has mentioned namedtuples
, which accomplish this kind of thing:
Foo = namedtuple('Foo', ['x'])
f = Foo(x='myattribute')
f.x
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.
For Python 3,
class Obj: pass
o = Obj()
o.name = 'gary'
o.age = 32
o
# <__main__.Obj at 0x17235ca65c0>
o.__dict__
# {'name': 'gary', 'age': 32}
Functions can have attributes in Python 3. Compared to a naked class, you can save one whole line of code.
naked = lambda: None
naked.foo = 'bar'
In some cases extending a dict
can help you
like:
class SpecificModelData(dict):
pass
...
class Payload(dict):
... enter code here
why a dict
? it works nicely together with serializers.
Why new class? – it gives you a name and a new type
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'
Perhaps you are looking for something like this:
myobject={}
myobject['foo']='bar'
then it can be called like:
print myobject['foo']
or you could use a class object for this:
class holder(object):
pass
then you can use something like this:
hold=holder()
hold.myobject='bar'
print hold.myobject
You would need to subclass object first like this…
class Myobject(object):
pass
myobject1 = Myobject()
myobject1.foo = 'bar'
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
.
class NakedObject(object):
pass
myobject = NakedObject()
myobject.foo = 'bar'
You should probably just use a dict, as per @PsychicOak’s answer.
However, if you really want an object you can manipulate, try:
class FooClass(object): pass
You can then assign attributes on FooClass
itself, or on instances, as you wish.
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')
I usually prefer to create a null object for my class:
class User(Model):
username = CharField()
password = CharField()
NONE_USER = User(username='', password='')
Then I use it where I would use your naked object.
I’m coming here very late, but I’m surprised nobody has mentioned namedtuples
, which accomplish this kind of thing:
Foo = namedtuple('Foo', ['x'])
f = Foo(x='myattribute')
f.x
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.
For Python 3,
class Obj: pass
o = Obj()
o.name = 'gary'
o.age = 32
o
# <__main__.Obj at 0x17235ca65c0>
o.__dict__
# {'name': 'gary', 'age': 32}
Functions can have attributes in Python 3. Compared to a naked class, you can save one whole line of code.
naked = lambda: None
naked.foo = 'bar'
In some cases extending a dict
can help you
like:
class SpecificModelData(dict):
pass
...
class Payload(dict):
... enter code here
why a dict
? it works nicely together with serializers.
Why new class? – it gives you a name and a new type