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

问题描述 投票:45回答:10

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

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

有比这更简洁的方法吗?

x1.foo = 1
x2.foo = 2
x3.foo = 3
x4.foo = 4
myfunc([x1, x2, x3, x4])

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

myfunc([<foo=1>, <foo=2>, <foo=3>, <foo=4>])

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

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

python anonymous-types
10个回答
41
投票

我喜欢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

0
投票

这就是我做的方式:

from mock import patch
import requests

class MockResponse:

    def __init__(self, text, status_code):
        self.text = text
        self.status_code = status_code


class TestSomething(unittest.TestCase):

    @patch('requests.get',return_value=MockResponse('the result',200))
    def test_some_request(self, *args, **kwargs):
        response = requests.get('some.url.com')
        assert response.text=='the result'
        assert response.status_code=='200'

39
投票

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

>>> obj = type('',(object,),{"foo": 1})()
>>> obj.foo
1

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))

6
投票

所以写信,搜索Python! o.o

>>> Object = lambda **kwargs: type("Object", (), kwargs)

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

>>> person = Object(name = "Bernhard", gender = "male", age = 42)
>>> person.name
'Bernhard'
>>>

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

>>> Object = lambda **kwargs: type("Object", (), kwargs)()

4
投票

非优雅:

def mock(**attrs):
    r = lambda:0
    r.__dict__ = attrs
    return r 

def test(a, b, c, d):
    print a.foo, b.foo, c.foo, d.foo

test(*[mock(foo=i) for i in xrange(1,5)])
# or
test(mock(foo=1), mock(foo=2), mock(foo=3), mock(foo=4))

4
投票

另一个明显的黑客:

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

print(foo1.x, foo2.y)

但是对于你的确切用例,直接调用一个带有匿名对象的函数,我不知道任何一个更简洁的问题

myfunc(type('', (object,), {'foo': 3},), type('', (object,), {'foo': 4}))

丑陋,做的工作,但不是真的。


4
投票

从Python 3.3开始,有types.SimpleNamespace完全符合您的要求:

myfunc([types.SimpleNamespace(foo=1), types.SimpleNamespace(foo=2), types.SimpleNamespace(foo=3), types.SimpleNamespace(foo=4)])

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

_ = types.SimpleNamespace
myfunc([_(foo=1), _(foo=2), _(foo=3), _(foo=4)])

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


4
投票

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

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

mock = Mock(foo=1)
mock.foo  // 1

0
投票
anonymous_object = type('',(),{'name':'woody', 'age':'25'})()
anonymous_object.name
> 'woody'

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

© www.soinside.com 2019 - 2024. All rights reserved.