38

创建可以为其分配属性的裸对象的最简单方法是什么?

具体用例是:我正在对一个 Django 对象实例进行各种操作,但有时该实例是 None (有实例)。在这种情况下,我想创建最简单的假对象,以便我可以为其属性分配值(例如。myobject.foo = 'bar')。

基本上我正在寻找这段 Javascript 的 Python 等价物:

myobject = {}
myobject.foo = 'bar'

我知道我可以为此使用模拟对象/库,但我希望有一个非常简单的解决方案(就像上面的 Javascript 一样简单)。有没有办法创建一个裸对象实例?就像是:

myobject = object()
myobject.foo = 'bar'
4

12 回答 12

45

您需要先创建一个简单的类:

class Foo(object):
    pass

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

你可以把它做成这样的单行:

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

对函数的调用type与前面的class语句相同。

如果你想真正做到最小...

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

关键是内置类型(例如listobject)不支持用户定义的属性,因此您需要使用class语句或调用type.

于 2012-05-30T20:20:38.777 回答
23

如果你使用 Python >= 3.3,你总是可以使用SimpleNamespace;它包含在 Pythontypes模块中。

SimpleNamespace很棒,因为您还可以repr免费获得等效测试;即使对于极简主义的对象,这两者也可能派上用场。

翻译 OP 问题中的 JavaScript 如下所示:

from types import SimpleNamespace

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

您还可以在实例化SimpleNamespace时使用关键字参数。这些参数将成为实例化SimpleNamespace的属性:

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

因此,将字典转换为SimpleNamespace对象的一种快速简便的方法( 前提是字典键是正确的标识符)如下所示:

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

Python >= 3.7 的数据类基本上是“<strong> mutable named tuples ”。如果您有很多数据对象,这可能是您可能想要使用的东西。

于 2018-03-22T20:47:42.510 回答
7

使用模块:

sudo pip install bunch

一堆是允许通过dict.key语法访问其内容的字典。

然后像这样:

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')
于 2012-05-30T20:30:24.780 回答
4
class NakedObject(object):
    pass

myobject = NakedObject()
myobject.foo = 'bar'
于 2012-05-30T20:20:50.477 回答
4

我很晚才来这里,但我很惊讶没有人提到namedtuples,它完成了这种事情:

Foo = namedtuple('Foo', ['x'])
f = Foo(x='myattribute')
f.x
于 2016-04-12T17:59:41.043 回答
2

在 Python 3 中,函数可以有属性。与裸类相比,您可以节省一整行代码。

naked = lambda: None
naked.foo = 'bar'
于 2018-07-01T19:16:51.353 回答
2

对于 Python 3,

class Obj: pass

o = Obj()
o.name = 'gary'
o.age = 32

o
# <__main__.Obj at 0x17235ca65c0>

o.__dict__
# {'name': 'gary', 'age': 32}
于 2018-06-04T11:52:33.510 回答
1

您需要像这样首先对对象进行子类化...

class Myobject(object):
    pass

myobject1 = Myobject()
myobject1.foo = 'bar'
于 2012-05-30T20:19:55.370 回答
0

也许您正在寻找这样的东西:

myobject={}
myobject['foo']='bar'

那么它可以被称为:

print myobject['foo']

或者您可以为此使用类对象:

class holder(object):
    pass

那么你可以使用这样的东西:

hold=holder()
hold.myobject='bar'
print hold.myobject
于 2012-05-30T20:19:08.197 回答
0

根据@PsychicOak 的回答,您可能应该只使用字典。

但是,如果您真的想要一个可以操作的对象,请尝试:

class FooClass(object): pass

FooClass然后,您可以根据需要为其自身或实例分配属性。

于 2012-05-30T20:21:19.027 回答
0

我通常更喜欢为我的类创建一个空对象:

class User(Model):
    username = CharField()
    password = CharField()


NONE_USER = User(username='', password='')

然后我在我会使用你的裸体物体的地方使用它。

于 2012-05-30T20:34:13.990 回答
0

在某些情况下,扩展 adict可以帮助您

喜欢:

class SpecificModelData(dict):
   pass
   ...

class Payload(dict):
   ... enter code here

为什么dict?它与序列化程序一起工作得很好。

为什么是新班?- 它给你一个名字和一个新的类型

于 2021-12-02T15:29:19.547 回答