31

How do I create objects on the fly in Python? I often want to pass information to my Django templates which is formatted like this:

{'test': [a1, a2, b2], 'test2': 'something else', 'test3': 1}

which makes the template look untidy. so I think it's better to just create an object which is like:

class testclass():
    self.test = [a1,a2,b2]
    self.test2 = 'someting else'
    self.test3 = 1
testobj = testclass()

so I can do:

{{ testobj.test }}
{{ testobj.test2 }}
{{ testobj.test3 }}

instead of calling the dictionary.

Since I just need that object once, is it possible to create it without writing a class first? Is there any short-hand code? Is it ok to do it like that or is it bad Python?

0

9 Answers 9

35

You can use built-in type function:

testobj = type('testclass', (object,), 
                 {'test':[a1,a2,b2], 'test2':'something else', 'test3':1})()

But in this specific case (data object for Django templates), you should use @Xion's solution.

Sign up to request clarification or add additional context in comments.

3 Comments

Please don't do this. Simple is better than complex.
@number5 I will vote for your answer if you also suggest not to use this code! (at least not for this specific case)
Although this is really handy for creating ad hoc objects for stubbing during testing, i.e. from a dictionary. Thanks.
32

There is another solution in Python 3.3+ types.SimpleNamespace

from types import SimpleNamespace
test_obj = SimpleNamespace(a=1, b=lambda: {'hello': 42})

test_obj.a
test_obj.b()

Comments

29

In Django templates, the dot notation (testobj.test) can resolve to the Python's [] operator. This means that all you need is an ordinary dict:

testobj = {'test':[a1,a2,b2], 'test2':'something else', 'test3':1}

Pass it as testobj variable to your template and you can freely use {{ testobj.test }} and similar expressions inside your template. They will be translated to testobj['test']. No dedicated class is needed here.

2 Comments

thank you, that solved the django related part of my problem :) i just checked the other answer because people coming here from google would probably prefer to see the python related answer.
@JasonTS, the python related answer would be to use Karl Knechtel's answer of collections.namedtuple.
17

Use collections.namedtuple.

1 Comment

Allows inheritance?
3

use building function type: document

>>> class X:
...     a = 1
...
>>> X = type('X', (object,), dict(a=1))

first and second X are identical

Comments

3

if you just need a "QuickRecord" you can simply declare a empty class
and you can use it without having to instantiate an object...
(just seize the dynamic features of python language... "á la Javascript")

# create an empty class...
class c1:pass

# then just add/change fields at your will
c1.a = "a-field"
c1.b = 1
c1.b += 10
print( c1.a, " -> ", c1.b )

# this has even the 'benesse' of easealy taking a 
# snapshot whenever you want

c2 = c1()
print( c2.a, " -> ", c2.b )

Comments

2

Here's a rogue, minimalist way to create an object. A class is an object, so just commandeer the class definition syntax as if it were a Python object literal:

class testobj(object):
    test = [a1,a2,b2]
    test2 = 'something else'
    test3 = 1

Class variables are the members of the object, and are easily referenced:

assert testobj.test3 == 1

This is weird, a class never used as a class: it's never instantiated. But it's a low-clutter way to make an ad hoc, singleton object: The class itself is your object.

2 Comments

Note thant the class as an object have large memory footprint and sensible amount of time for it's creation.
@intellimath your point that a class comes with a lot of baggage is a good one, and one should be aware of its consequences. I would note that computer memory gets cheaper while human memory trends ever more precious. A singleton object that's not used repetitively has little cost. A lean syntax that's quick to read and understand has solid benefits.
1

for the sake of completeness, there is also recordclass:

from recordclass import recordclass
Test = recordclass('Test', ['test', 'test1', 'test2'])
foo = Test(test=['a1','a2','b2'], test1='someting else', test2=1)

print(foo.test)
.. ['a1', 'a2', 'b2']

Comments

0

The code below also require a class to be created however it is shorter:

 >>>d = {'test':['a1','a2','b2'], 'test2':'something else', 'test3':1}
 >>> class Test(object):
 ...  def __init__(self):
 ...   self.__dict__.update(d)
 >>> a = Test()
 >>> a.test
 ['a1', 'a2', 'b2']
 >>> a.test2
 'something else'

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.