11

Does there exist special class in python to create empty objects? I tried object(), but it didn't allow me to add fields. I want to use it like this:

obj = EmptyObject()
obj.foo = 'far'
obj.bar = 'boo'

Should I each time(in several independent scripts) define new class like this?

class EmptyObject:
    pass

I use python2.7

sbeliakov
  • 2,169
  • 1
  • 20
  • 37
  • 2
    It's two lines of fairly self-evident code, I see no problem with repeating it. Even if you had to add a new `import` to obtain an existing `EmptyObject`, the net savings would be minor. – user4815162342 Mar 19 '14 at 14:46
  • You could even put it on one line, no? – 2rs2ts Mar 19 '14 at 14:52
  • 1
    Have you considered [namedtuple](http://docs.python.org/2/library/collections.html#collections.namedtuple)? I have a sense you're reinventing a wheel. – kojiro Mar 19 '14 at 14:53
  • @kojiro What if OP wants to be able to add attributes dynamically, a la JavaScript objects? – 2rs2ts Mar 19 '14 at 14:56
  • 1
    @2rs2ts so, like [Bunch](http://stackoverflow.com/a/2597440/418413). Which, personally, I think is a great way to generate problems. – kojiro Mar 19 '14 at 14:59
  • Have you looked into using an attrdict. There are many implementations of it out there. – cmd Mar 19 '14 at 17:12
  • When appropriate, I use `class Struct: pass` because the name 'Struct' reflects how I am using the instances. – dsh Oct 15 '15 at 15:20

4 Answers4

10

types.SimpleNamespace was introduced with Python 3.3 to serve this exact purpose. The documentation also shows a simple way to implement it yourself in Python, so you can add it to your pre-Python 3.3 setup and use it as if it was there (note that the actual implementation is done in C):

class SimpleNamespace (object):
    def __init__ (self, **kwargs):
        self.__dict__.update(kwargs)
    def __repr__ (self):
        keys = sorted(self.__dict__)
        items = ("{}={!r}".format(k, self.__dict__[k]) for k in keys)
        return "{}({})".format(type(self).__name__, ", ".join(items))
    def __eq__ (self, other):
        return self.__dict__ == other.__dict__

But of course, if you don’t need its few features, a simple class Empty: pass does just the same.

poke
  • 369,085
  • 72
  • 557
  • 602
  • Unfortunately as I've said I use python2.7 – sbeliakov Mar 19 '14 at 14:53
  • 4
    @maggot092 And as I have said, you can easily add the implementation to your Python 2 project and use it as if it was there… – poke Mar 19 '14 at 14:54
  • In this case as you have also said I don't see advantage comparing defining Emty class – sbeliakov Mar 19 '14 at 14:57
  • Well, the big advantage would be using a type that does exist in a future Python version, so using an equivalent type will definitely make your intention clear. – poke Mar 19 '14 at 15:02
  • 2
    The OP was concerned about having to repeat the trivial two lines in each script. Repeating these 9 lines in every script instead appears like a cure that is worse than the disease. – user4815162342 Mar 19 '14 at 15:19
  • @user4815162342 Type definitions can—and should—easily be moved into separate modules, especially when you access the type multiple times from different locations. – poke Mar 19 '14 at 15:21
  • The separate module is a new dependency, which makes it harder, not easier, to distribute the script to a different machine. It can be done, but it's a tradeoff. In the context of the question which asks how to avoid the two-line creation of empty container class, creating a separate module for those two lines is evidently overkill. – user4815162342 Mar 19 '14 at 16:13
8

If you are looking for a place holder object to which you can add arbitrary static members, then the closest I got is an empty lambda function.

obj = lambda: None    # Dummy function
obj.foo = 'far'
obj.bar = 'boo'

print obj.foo, obj.bar
# far boo

Remember: obj is not an object of a class, object doesn't mean class instance, because in Python classes and functions are objects at runtime just like class instances

dsh
  • 12,037
  • 3
  • 33
  • 51
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • 1
    Why the argument? You could just as well use `lambda: 0`. I'd not use it still though, as this makes it hard to figure out why you'd create the `lambda` in the first place. – Martijn Pieters Mar 19 '14 at 14:50
  • 9
    Mhh... While this is certainly interesting, I sure as hell wouldn't want to see this in production code. – Lukas Graf Mar 19 '14 at 14:51
  • My upvote for originality, but I agree with Lukas Graf, this solution is not for production – sbeliakov Mar 19 '14 at 15:14
7

There is no types.SimpleNamespace in Python 2.7, you could use collections.namedtuple() for immutable objects instead:

>>> from collections import namedtuple
>>> FooBar = namedtuple('FooBar', 'foo bar')
>>> FooBar('bar', 'foo')
FooBar(foo='bar', bar='foo')

Or argparse.Namespace:

>>> from argparse import Namespace
>>> o = Namespace(foo='bar')
>>> o.bar = 'foo'
>>> o
Namespace(bar='foo', foo='bar')

See also, How can I create an object and add attributes to it?

jfs
  • 399,953
  • 195
  • 994
  • 1,670
2

You can create a new type dynamically with the fields you want it to have using the type function, like this:

x = type('empty', (object,), {'foo': 'bar'})
x.bar = 3
print(x.foo)

This is not entirely what you want though, since it will have a custom type, not an empty type.

Hampus Nilsson
  • 6,692
  • 1
  • 25
  • 29