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?
-
+1, I was just about to ask the exact same question but then remembered to search for an existing one first! Good answers below, too.Edmund– Edmund2010年03月31日 22:53:49 +00:00Commented Mar 31, 2010 at 22:53
-
very good question, i am having a similar problemtrevorKirkby– trevorKirkby2013年11月26日 20:27:41 +00:00Commented Nov 26, 2013 at 20:27
-
possible duplicate of Can't set attributes of object classMartijn Pieters– Martijn Pieters2013年12月17日 16:03:52 +00:00Commented Dec 17, 2013 at 16:03
-
@MartijnPieters my question is raised on 2 Jul 09. The duplicate you cited is raised on 7 Oct 09. Why would you raise a duplicate flag on this question?Anthony Kong– Anthony Kong2013年12月17日 23:20:22 +00:00Commented Dec 17, 2013 at 23:20
-
@AnthonyKong: Because we (python chat room) are trying to consolidate the duplicates and into one with a clear problem description and canonical answer. Note that it doesn't matter that much which question was earlier for dupe votes, more which one can work better as a canonical dupe target.Martijn Pieters– Martijn Pieters2013年12月17日 23:24:38 +00:00Commented Dec 17, 2013 at 23:24
4 Answers 4
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.
7 Comments
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
1 Comment
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
2 Comments
sentinel=object(). It WOULD be modestly handy to have an "objectwithadict" builtin at hand rather than having to make new classes for the purpose, soemetimes;-).class ObjectWithADict(object): pass?Here's another alternative, as short as I could make it:
>>> dummy = type('', (), {})()
>>> dummy.foo = 5
>>> dummy.foo
5