在Python中创建一个空对象


77

是否有在Python中定义空对象的快捷方式,还是总是需要创建自定义空类的实例?

编辑:我的意思是一个空的对象可用于鸭打字。

Answers:


102

您可以使用type动态创建一个新类,然后实例化它。像这样:

>>> t = type('test', (object,), {})()
>>> t
<__main__.test at 0xb615930c>

要键入的参数是:类名,基类的元组和对象的字典。可以包含函数(对象的方法)或属性。

您实际上可以将第一行缩短为

>>> t = type('test', (), {})()
>>> t.__class__.__bases__
(object,)

因为默认情况下,type创建从对象继承的新样式类。

type在Python中用于元编程

但是,如果您只想创建对象的实例。然后,只需创建它的一个实例。就像lejlot暗示的那样。

像这样创建一个新类的实例有一个重要的区别,可能有用。

>>> a = object()
>>> a.whoops = 1
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'whoops'

如:

>>> b = type('', (), {})()
>>> b.this_works = 'cool'
>>> 

75

是的,在Python 3.3中添加了SimpleNamespace

与对象不同,使用SimpleNamespace可以添加和删除属性。如果使用关键字参数初始化SimpleNamespace对象,则将它们直接添加到基础名称空间。

例:

import types

x = types.SimpleNamespace()
x.happy = True

print(x.happy) # True

del x.happy
print(x.happy) # AttributeError. object has no attribute 'happy'

48

创建空对象的一种简单但不那么恐怖的方法是利用以下事实:函数是Python中的对象,包括Lambda函数:

obj = lambda: None
obj.test = "Hello, world!"

例如:

In [18]: x = lambda: None

In [19]: x.test = "Hello, world!"

In [20]: x.test
Out[20]: 'Hello, world!'

我喜欢这个解决方案,因为不需要赋予一个名字
休·珀金斯

4
嗯,但它有您无法分配的缺点x.__class__.somefunc
休·珀金斯

1
当我尝试copy.deepcopy()此对象时,此解决方案有问题。python 3中的types.SimpleNamespace()是更好的解决方案。
cn123h

12

“空对象”是什么意思?类的实例object?您可以简单地运行

a = object()

还是您的意思是初始化为空引用?那你可以用

a = None

21
我想知道OP将能够做什么,因为aasobject()None因为在这样的情况下,a没有命名空间__dict__,也没有属性可以a像这样添加a.x = 10
eyquem 2014年

1
确实,a = object(); a.foo = 'bar'AttributeError: 'object' object has no attribute 'foo'
巴斯基

3

所有提出的解决方案都有些尴尬。

我发现了一种方法,该方法并非不客气,但实际上符合原始设计。

>>> from mock import Mock
>>> foo = Mock(spec=['foo'], foo='foo')
>>> foo.foo
'foo'
>>> foo.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../virtualenv/local/lib/python2.7/site-packages/mock/mock.py", line 698, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'bar'

请参阅此处的unittest.mock文档。


1

构造一个新的空Set对象。如果提供了可选的iterable参数,则使用从迭代获得的元素更新集合。使用协议部分中所述的协议,可迭代的所有元素都应该是不可变的或可以转换为不可变的,以自动转换为不可变。

例如:

myobj = set()
for i in range(1,10): myobj.add(i)
print(myobj)

1

您是在问题中说过的,但由于没有答案在代码中提及,这可能是最干净的解决方案之一:

class Myobject:
    pass

x = Myobject()
x.test = "Hello, world!"  # working


1

您可以使用

x = lambda: [p for p in x.__dict__.keys()]

然后

x.p1 = 2
x.p2 = "Another property"

x()
# gives
# ['p1', 'p2']

[(p, getattr(x,p)) for p in x()]
# gives
# [('p1', 2), ('p2', 'Another property')]

0

我认为,最简单的方法是:

def x():pass
x.test = 'Hello, world!'
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.