Anthony Kong
Anthony Kong

Reputation: 40874

Python Language Question: attributes of object() vs Function

In python, it is illegal to create new attribute for an object instance like this

>>> a = object()
>>> a.hhh = 1

throws

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hhh'

However, for a function object, it is OK.

>>> def f():
...   return 1
...
>>> f.hhh = 1

What is the rationale behind this difference?

Upvotes: 17

Views: 1469

Answers (4)

Gringo Suave
Gringo Suave

Reputation: 31958

Here's another alternative, as short as I could make it:

>>> dummy = type('', (), {})()
>>> dummy.foo = 5
>>> dummy.foo
5

Upvotes: 0

S.Lott
S.Lott

Reputation: 392050

The rationale is that an instance of object() is a degenerate special case. It "is" an object but it isn't designed to be useful by itself.

Think of object as a temporary hack, bridging old-style types and classes. In Python 3.0 it will fade into obscurity because it will no longer be used as part of

class Foo( object ):
    pass

f = Foo()
f.randomAttribute = 3.1415926

Upvotes: 1

gahooa
gahooa

Reputation: 137592

Alex Martelli posted an awesome answer to your question. For anyone who is looking for a good way to accomplish arbitrary attributes on an empty object, do this:

class myobject(object):
    pass

o = myobject()
o.anything = 123

Or more efficient (and better documented) if you know the attributes:

class myobject(object):
    __slots__ = ('anything', 'anythingelse')

o = myobject()
o.anything = 123
o.anythingelse = 456

Upvotes: 7

Alex Martelli
Alex Martelli

Reputation: 882771

The reason function objects support arbitrary attributes is that, before we added that feature, several frameworks (e.g. parser generator ones) were abusing function docstrings (and other attribute of function objects) to stash away per-function information that was crucial to them -- the need for such association of arbitrary named attributes to function objects being proven by example, supporting them directly in the language rather than punting and letting (e.g.) docstrings be abused, was pretty obvious.

To support arbitrary instance attributes a type must supply every one of its instances with a __dict__ -- that's no big deal for functions (which are never tiny objects anyway), but it might well be for other objects intended to be tiny. By making the object type as light as we could, and also supplying __slots__ to allow avoiding per-instance __dict__ in subtypes of object, we supported small, specialized "value" types to the best of our ability.

Upvotes: 22

Related Questions