88

I'm debugging some Python that takes, as input, a list of objects, each with some attributes.

I'd like to hard-code some test values -- let's say, a list of four objects whose "foo" attribute is set to some number.

Is there a more concise way than this?

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

Ideally, I'd just like to be able to say something like:

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

(Obviously, that is made-up syntax. But is there something similar that really works?)

Note: This will never be checked in. It's just some throwaway debug code. So don't worry about readability or maintainability.

14 Answers 14

91

I found this: http://www.hydrogen18.com/blog/python-anonymous-objects.html, and in my limited testing it seems like it works:

>>> obj = type('',(object,),{"foo": 1})()
>>> obj.foo
1
Sign up to request clarification or add additional context in comments.

3 Comments

Brilliant! And is true one-liner!
Love it. This also works with other classes and initializing, for example here’s an anonymous object derived from Python’s dictionary and initialized with two entries: type("", (dict,), {})({"a": 1, "b": 2})
using mock object it's even simpler, see stackoverflow.com/a/75360777/1161025
58

I like Tetha's solution, but it's unnecessarily complex.

Here's something simpler:

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

6 Comments

However, if you're creating a whole bunch of these, you might save some time/memory by using the given dictionary instead of creating a new one and copying all the entries. Doesn't really matter, though.
well, I might be subjective, but I see no substantial simplification. Yes, you use init and update, but youre still fiddling around with dict.
You're right, there's no significant simplification. It's just shorter and doesn't use new, that's all.
If you want convenient syntax, _ is a valid class name in python, and isn't really any more indecipherable than the version posited in the question.
With recent Python feature, you can use "def mock(**kwargs): return type('',(),kwargs)()", and do "a = mock(foo=1)"
|
45

Wow, so brief, such Python! O.o

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

Then you can use Object as a generic object constructor:

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

Now technically Object creates a class object, not an object-object:

>>> type(person)
<class 'type'>
>>> person()
<__main__.Object object at ...>

You could already treat it like an anonymous object but you better modify the definition of Object like so: just append a pair of parenthesis to create an immediate instance:

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

4 Comments

This is the only "non-horrible" solution I've seen here.
Nice. Should be a PEP to add a new keyword. Maybe change the name from Object to Anon though?
Alternatively, ` def thingy(**kwargs): return type("Object", (), kwargs)() `
beautiful solution
18

I will use lambda

obj = lambda: None
obj.s = 'abb'
obj.i = 122

4 Comments

What is the difference with obj = {}?
@AndersLindén You'll get AttributeError with {}, one cannot set attributes on a dict.
aaaand we have a real answer. +million.. I'm done using a dict as a container for relatively simple objects that I don't want to create a class for. One minor inconvenience: if you need to JSON serialize this, you need to use obj.__dict__ That's an inconvenience I'm willing to live with.
I really love this answer. it is taking advantage of the fact than lambda allows __setattr()__ on any key, value. Perhaps not "pythonic" yet, but it will be if we all start using it!!!
17

Maybe you can use namedtuple to solve this as following:

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

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

Comments

16

Have a look at this:


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

Comments

10

As of Python 3.3, there's types.SimpleNamespace that does exactly what you want:

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

That's a tad wordy, but you can clean it up with an alias:

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

And now that's actually pretty close to the fictional syntax in your question.

3 Comments

Credit to @RoadieRich for suggesting _ as the class name in an earlier comment.
If using _ bothers you (it feels a bit icky and unpythonic to me), and you really don't want to type so much, you can also just from types import SimpleNamespace as Nsp and use Nsp like _ in your answer.
@JJC of course! The coding standards I currently work under don't allow renaming on import like that, so I tend to forget that's even an option.
8

Another obvious hack:

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

print(foo1.x, foo2.y)

But for your exact usecase, calling a function with anonymous objects directly, I don't know any one-liner less verbose than

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

Ugly, does the job, but not really.

Comments

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

There is a cool way but hard to understand. It use type() create a no-named class with default init params, then init it without any param and get the anonymous object.

2 Comments

Python should support anonymous types. They are very handy in C#. This is the cleanest solution out of all the answers.
@michael Yes, it's one of C# 's cool features. C# has a really nice syntax design.
4

Non classy:

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

Comments

2
>>> from unittest.mock import Mock
>>> obj = Mock(foo=1)
>>> obj.foo
1

I was surprised to not find this in the answers already.

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

I think it and SimpleNamespace are the most straight-forward and "canonical" ways to create a dummy/anonymous object in Python. They work since Python 3.3 (2012). I would base the choice of one of them depending on the context of usage.

Comments

-1

This is how I did it:

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'

Comments

-1

If you are using Python 3.7 or above, you can use named tuples to enhance the created object with immutability, docstring, and handy tuple methods:

from collections import namedtuple

PyObj = lambda **kwargs: namedtuple('PyObj', kwargs.keys())._make(kwargs.values())

o = PyObj(foo = 1)
print(o)
# prints: PyObj(foo=1)
o.foo
# returns: 1
o.foo = 0
# exception:
# Traceback (most recent call last):
#   File "<stdin>", line 1, in <module>
# AttributeError: can't set attribute

print(PyObj(foo = 1, bar = 'baz'))
# prints: PyObj(foo=1, bar='baz')

Python 3.7+ is required to ensure keys and values are in the same order.

However, if the list of attributes is predefined, you can use namedtuple directly, as Huachao suggested, there's no need to define the PyObj function and you can use it in v2.7.

from collections import namedtuple
foo = namedtuple('Foo', 'foo')

myfunc = lambda l: [x.foo * 10 for x in l]
myfunc([foo(1), foo(2), foo(3), foo(4)])
# returns [10, 20, 30, 40]

Plus, it looks more like the syntax you are looking for.

Comments

-2

Yes, I very much missed the straightforward anonymous objects in JavaScript, particularly in function return values, where you can just say

function george() { 
    return {fred:6, jim:9}; 
}
x = george();
y = x.fred;

You can use a dictionary to get the same effect, but all those square brackets and single quotes look muddly. So I now do the following, which works:

def fred():
    class rv:
        x=0
    rv.y = 6
    return rv

def jim():
    class rv:
        x=0
    rv.y = 9
    return rv
a = fred()
b = jim()
print(a.y, b.y, id(a.y), id(b.y))

It would feel nicer to have a global class RV, and instantiate it to get the same effect, but this way the function has no external dependencies.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.