Python anonymous classes

This post is as much to remind me of how to do this as anything else.

I sometimes find myself wanting anonymous classes; essentially, I want to be able to have objects which are just bags of properties. Clearly you can get most of this behaviour from a dictionary:

anon_object_0 = {}

and then assign properties as dictionary entries:

anon_object_0['property'] = 1

But, in my head at least, there is a difference in intent when manipulating a dictionary, and when manipulating an object with properties, and sometimes I want to explicitly be using an object, with property-accessor syntax.

It's also useful to be able to generate things that behave like objects, for driving interfaces which expect objects of a certain type; that is, "mock objects", thought that term means different things to different people. (and there are Python libraries for those already). That use case is most often seen in testing, but I've needed it in production code occasionally.

So usually, when I want anonymous objects, I want to be able to set them up trivially; I don't want to pull in a library, nor do I want a lengthy definition - one line is verging on too much already.

There's basically two ways to create useful anonymous classes in Python.

The obvious way is just:

class Anonymous(object): pass

Thereafter you can do:

anon_object_1 = Anonymous()
anon_object_1.property = 1

My preferred way takes advantage of the python type constructor; this creates an anonymous class:

type("", (), {})

and this, of course, creates an instance:

anon_object_2 = type("", (), {})()

which I prefer to the first. Firstly, it genuinely is a one-liner to define an anonymous object, I don't have to worry about the anonymous class per se; and secondly, for the relatively unimportant reason that

>>> anon_object_1
<__main__.Anonymous object at 0x6f8b0>
>>> type(anon_object_1)
<class '__main__.Anonymous'>

>>> anon_object_2
<__main__. object at 0x6f8f0>
>>> type(anon_object_2)
<class '__main__.'>

The first contains a reference to the name of its defining class, so is not exactly anonymous; and it's invaded your namespace a little. Largely in an unimportant way, since you can re-use that part of your namespace easily enough, but this is true:

>>> 'Anonymous' in globals()
True

where it wasn't before.

An interesting variation of the first way can be seen in Peter Norvig's Python Infrequently Asked Questions - he has a "Struct" class, which has a series of useful methods which help with initialization and update of arbitrary properties.

Comments have been automatically disabled | digg this | reddit | del.icio.us