如何在Python中动态创建对象?

29

我该如何在Python中动态创建对象?我经常想要将格式为以下内容的信息传递给我的Django模板:

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

这会使模板看起来不整洁,所以我认为最好只创建一个类似于以下对象的对象:

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

那么我可以这样做:

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

不用调用字典,因为我只需要这个对象一次,有没有可能在不先编写类的情况下创建它?有没有简便的代码?这样做可以吗,还是说这是不好的Python编程风格?


10
首先,你需要让苍蝇保持不动。然后你需要制造一些非常小的物品...(抱歉,忍不住开玩笑了。) - Hot Licks
9个回答

34
你可以使用内置的type函数:
testobj = type('testclass', (object,), 
                 {'test':[a1,a2,b2], 'test2':'something else', 'test3':1})()

但在这种特定情况下(Django模板的数据对象),你应该使用 @Xion 的解决方案。


8
请不要这样做。简单比复杂更好。 - Karl Knechtel
3
如果您建议不要在这种情况下使用这段代码,我将投票支持您的答案!(至少不要用这段代码) - Tommaso Barbugli
1
虽然这对于在测试期间创建临时对象(例如从字典中)进行存根非常方便,但感谢。 - Rohan Nicholls

29

在Python 3.3+中有另一种解决方案: types.SimpleNamespace

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

test_obj.a
test_obj.b()

27
在Django模板中,点符号(testobj.test)可以解析为Python的[]操作符。这意味着你只需要一个普通的字典:
testobj = {'test':[a1,a2,b2], 'test2':'something else', 'test3':1}

将它作为testobj变量传递给您的模板,您可以在模板内自由使用{{ testobj.test }}和类似的表达式。它们将被转换为testobj ['test']。这里不需要专门的类。


谢谢,这解决了我问题中与 Django 相关的部分 :) 我只是检查了另一个答案,因为从 Google 到这里的人可能更喜欢看 Python 相关的答案。 - JasonTS
1
@JasonTS,与Python相关的答案是使用Karl Knechtel的collections.namedtuple答案。 - Duncan

17

允许继承吗? - Memmo

3
使用建立函数类型:文档
>>> class X:
...     a = 1
...
>>> X = type('X', (object,), dict(a=1))

第一和第二个X是相同的。


2
如果你只需要一个“QuickRecord”,你可以简单地声明一个空类,而不必实例化一个对象...(就像使用JavaScript一样,利用Python语言的动态特性即可)。
# 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 )

2
这是一种叛逆、极简的创建对象的方式。因为类就是一个对象,所以只需像使用Python对象字面量那样占用类定义语法即可:

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

类变量是对象的成员,并且很容易引用:

最初的回答:

assert testobj.test3 == 1

这很奇怪,一个从未用作类的类:它从未被实例化。但这是一种低杂乱的方式来创建一个临时的单例对象:类本身就是你的对象。

最初的回答:

这个类没有被当做类来使用,也从未被实例化,但这是一种简单的方法来创建一个临时的单例对象:这个类本身就是你的对象。


请注意,类作为对象具有较大的内存占用和相当长的创建时间。 - intellimath
@intellimath,你提到类带来的负担很多,这是一个很好的观点,人们应该意识到它的后果。我想指出的是,随着计算机内存变得越来越便宜,人类记忆变得越来越珍贵。一个不重复使用的单例对象几乎没有成本。一个简洁的语法,快速阅读和理解,具有实实在在的好处。 - Bob Stein

1
为了完整起见,还有一个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']

0
下面的代码也需要创建一个类,但它更短:
 >>>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'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接