是否可以在Python中创建匿名对象?

mik*_*ike 48 python anonymous-types

我正在调试一些Python,它接受一个对象列表作为输入,每个对象都有一些属性.

我想硬编码一些测试值 - 比方说,一个四个对象的列表,其"foo"属性设置为某个数字.

有比这更简洁的方法吗?

x1.foo = 1
x2.foo = 2
x3.foo = 3
x4.foo = 4
myfunc([x1, x2, x3, x4])
Run Code Online (Sandbox Code Playgroud)

理想情况下,我只想说出类似的话:

myfunc([<foo=1>, <foo=2>, <foo=3>, <foo=4>])
Run Code Online (Sandbox Code Playgroud)

(显然,这是伪造的语法.但是有类似的东西真的有效吗?)

注意:这将永远不会被签入.它只是一些一次性的调试代码.所以不要担心可读性或可维护性.

Dzi*_*inX 43

我喜欢Tetha的解决方案,但它不必要地复杂.

这里更简单:

>>> class MicroMock(object):
...     def __init__(self, **kwargs):
...         self.__dict__.update(kwargs)
...
>>> def print_foo(x):
...     print x.foo
...
>>> print_foo(MicroMock(foo=3))
3
Run Code Online (Sandbox Code Playgroud)

  • 好吧,我可能是主观的,但我认为没有实质性的简化。是的,您使用 __init__ 并更新,但您仍在摆弄 __dict__。 (3认同)
  • 使用最近的Python功能,你可以使用"def mock(**kwargs):return type('',(),kwargs)()",并执行"a = mock(foo = 1)" (2认同)

Ner*_*ter 42

我发现了这个:http://www.hydrogen18.com/blog/python-anonymous-objects.html,在我的有限测试中它似乎有效:

>>> obj = type('',(object,),{"foo": 1})()
>>> obj.foo
1
Run Code Online (Sandbox Code Playgroud)


Tet*_*tha 16

看看这个:


class MiniMock(object):
    def __new__(cls, **attrs):
        result = object.__new__(cls)
        result.__dict__ = attrs
        return result

def print_foo(x):
    print x.foo

print_foo(MiniMock(foo=3))
Run Code Online (Sandbox Code Playgroud)


Hua*_*hao 11

也许你可以使用namedtuple来解决这个问题,如下所示:

from collections import namedtuple
Mock = namedtuple('Mock', ['foo'])

mock = Mock(foo=1)
mock.foo  // 1
Run Code Online (Sandbox Code Playgroud)


Nam*_* VU 11

我将使用拉姆达

obj = lambda: None
obj.s = 'abb'
obj.i = 122
Run Code Online (Sandbox Code Playgroud)

  • @AndersLindén 您将收到带有“{}”的 AttributeError,无法在“dict”上设置属性。 (3认同)
  • 与 `obj = {}` 有什么区别? (2认同)
  • aaa我们有一个真正的答案。+百万..我已经不再使用字典作为相对简单的对象的容器,我不想为其创建类。一个小不便:如果您需要 JSON 序列化它,则需要使用 obj.__dict__ 这是我愿意忍受的不便。 (2认同)

Dan*_*sen 8

如此简短,这样的Python!吴

>>> Object = lambda **kwargs: type("Object", (), kwargs)
Run Code Online (Sandbox Code Playgroud)

然后你可以Object用作通用对象构造函数:

>>> person = Object(name = "Bernhard", gender = "male", age = 42)
>>> person.name
'Bernhard'
>>>
Run Code Online (Sandbox Code Playgroud)

编辑:好吧,从技术上讲,这会创建一个类对象,而不是一个对象对象.但是您可以将其视为匿名对象,或者通过附加一对括号来立即创建实例来修改第一行:

>>> Object = lambda **kwargs: type("Object", (), kwargs)()
Run Code Online (Sandbox Code Playgroud)

  • 这是我在这里看到的唯一“不可怕”的解决方案。 (3认同)

小智 8

从 Python 3.3 开始,types.SimpleNamespace可以完全满足您的需求:

myfunc([types.SimpleNamespace(foo=1), types.SimpleNamespace(foo=2), types.SimpleNamespace(foo=3), types.SimpleNamespace(foo=4)])
Run Code Online (Sandbox Code Playgroud)

这有点罗嗦,但你可以用别名来清理它:

_ = types.SimpleNamespace
myfunc([_(foo=1), _(foo=2), _(foo=3), _(foo=4)])
Run Code Online (Sandbox Code Playgroud)

现在这实际上非常接近您问题中的虚构语法。

  • 如果使用 _ 困扰你(对我来说感觉有点恶心和不喜欢),并且你真的不想输入这么多,你也可以只`from types import SimpleNamespace as Nsp`并在你的答案中使用 Nsp like _ 。 (4认同)

woo*_*ody 6

anonymous_object = type('',(),{'name':'woody', 'age':'25'})()
anonymous_object.name
> 'woody'
Run Code Online (Sandbox Code Playgroud)

有一个很酷的方法,但很难理解。它使用 type() 创建一个带有默认初始化参数的无名类,然后在没有任何参数的情况下初始化它并获取匿名对象。


vla*_*ean 5

另一个明显的hack:

class foo1: x=3; y='y'
class foo2: y=5; x=6

print(foo1.x, foo2.y)
Run Code Online (Sandbox Code Playgroud)

但是对于您的确切用例,直接调用带有匿名对象的函数,我不知道有哪一种细节比

myfunc(type('', (object,), {'foo': 3},), type('', (object,), {'foo': 4}))
Run Code Online (Sandbox Code Playgroud)

丑陋,能胜任,但并非如此。