Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Python 3.1, object, and setattr()

1,011 views
Skip to first unread message

Ethan Furman

unread,
Apr 1, 2010, 9:46:33 AM4/1/10
to Python
Greetings!

Perhaps I woke up too early this morning, but this behaviour has me baffled:

Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.

--> test = object()

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

Shouldn't setattr() be creating the 'example' attribute? Any tips
greatly appreciated!

~Ethan~

Steve Howell

unread,
Apr 1, 2010, 10:16:26 AM4/1/10
to

On 2.6.2 the error seems to be limited to instances of object. If you
subclass object, you are fine. I do not know why that is so; I'm just
verifying that the behavior you see is not limited to 3.1.1.

Python 2.6.2 (release26-maint, Apr 19 2009, 01:56:41)
[GCC 4.3.3] on linux2


Type "help", "copyright", "credits" or "license" for more
information.

>>> class Foo(object): pass
...
>>> test = Foo()
>>> setattr(test, 'example', 123)
>>> test.example
123
>>> test = object()


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

It's probably good to subclass object anyway, with something like:

class Record(object):
pass

But I do not know your use case.

Steve Holden

unread,
Apr 1, 2010, 10:21:31 AM4/1/10
to pytho...@python.org
Ethan Furman wrote:
> Greetings!
>
> Perhaps I woke up too early this morning, but this behaviour has me
> baffled:
>
> Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit
> (Intel)] on win32
> Type "help", "copyright", "credits" or "license" for more information.
>
> --> test = object()
>
> --> setattr(test, 'example', 123)
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> AttributeError: 'object' object has no attribute 'example'
>
> Shouldn't setattr() be creating the 'example' attribute? Any tips
> greatly appreciated!
>
It's not just object, and it's not just the setattr() function. It's not
even just Python 3.1 for that matter! Later Python 2 implementations
have the same issue.

>>> x = 1
>>> setattr(x, 'example', 123)


Traceback (most recent call last):
File "<stdin>", line 1, in <module>

AttributeError: 'int' object has no attribute 'example'
>>> x.example = 123


Traceback (most recent call last):
File "<stdin>", line 1, in <module>

AttributeError: 'int' object has no attribute 'example'
>>>

There are limits to what you can do with the built-in types. No matter
how hard Python tries to make them look the same, ultimately the
built-in types are implemented differently from the types you create
yourself.

For efficiency reasons the attributes of the built-ins are stored in a
different way (that's more accessible to the C implementation) than
those of the declared types.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
See PyCon Talks from Atlanta 2010 http://pycon.blip.tv/
Holden Web LLC http://www.holdenweb.com/
UPCOMING EVENTS: http://holdenweb.eventbrite.com/

Steve Holden

unread,
Apr 1, 2010, 10:25:08 AM4/1/10
to pytho...@python.org
Ethan Furman wrote:
> Greetings!
>
> Perhaps I woke up too early this morning, but this behaviour has me
> baffled:
>
> Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit
> (Intel)] on win32
> Type "help", "copyright", "credits" or "license" for more information.
>
> --> test = object()
>
> --> setattr(test, 'example', 123)
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> AttributeError: 'object' object has no attribute 'example'
>
> Shouldn't setattr() be creating the 'example' attribute? Any tips
> greatly appreciated!
>
By the way, the "solution" is to create a subclass of object (which in
Python 3 simply requires you to declare a class! In Python 2 you'd have
to explicitly subclass object, or (equivalently) set your class's
metaclass to type with

__metaclass__ = type

Terry Reedy

unread,
Apr 1, 2010, 1:44:02 PM4/1/10
to pytho...@python.org
On 4/1/2010 10:16 AM, Steve Howell wrote:
> On Apr 1, 6:46 am, Ethan Furman<et...@stoneleaf.us> wrote:
>
> On 2.6.2 the error seems to be limited to instances of object. If you
> subclass object, you are fine. I do not know why that is so;

As the other Steve said, object is a built-in class; user-defined
subclasses of object are user-defined classes. (And all other built-in
classes are built-in subclasses of object, at least in 3.x.)

Python objects can have either a fixed or variable set of attributes. By
default, instances of user classes have an attribute dictionary
(__dict__) for a variable set of attributes.

>>> a = A()
>>> a.a = 3
>>> a.a
3
>>> a.__dict__
{'a': 3}

The exception is when '__slots__ = xxx' is part of the class definition.
It instances then have a fixed set of attributes.

>>> class C(): __slots__ = ()

>>> c = C()
>>> c.a = 1


Traceback (most recent call last):

File "<pyshell#8>", line 1, in <module>
c.a = 1
AttributeError: 'C' object has no attribute 'a'

The error message means that 'a' is not in the fixed set of instance
attributes (as defined by __slots__) for class C.

In general, instances of built-in classes do not have such attribute
dictionaries and one their attribute set is fixed (and often empty). It
is as if built-in classes have '__slots__ = xxx' as part of their
definition. In particular, object and others act like they have
'__slots__ = ()', which means they have no instance attributes.

There are two exceptions among built-in classes that I know of: type and
'function', (whose instances are user-defined functions).

>>> def f(): pass

>>> f.__dict__
{} # standard dict just as with user class instances

Instances of type are more complicated:

>>> C.__dict__
<dict_proxy object at 0x00F682F0>
>>> C.z = 3
>>> C.z
3

so the dict_proxy for user classes is writable

but
>>> int.__dict__
<dict_proxy object at 0x00F5CDD0>
>>> int.z = 3


Traceback (most recent call last):

File "<pyshell#18>", line 1, in <module>
int.z = 3
TypeError: can't set attributes of built-in/extension type 'int'

wheres for builtins, it is not.

Terry Jan Reedy


Ethan Furman

unread,
Apr 1, 2010, 3:14:35 PM4/1/10
to Python
Many thanks for the replies, and especially for the very detailed
explanation. Makes much more sense now.

~Ethan~

0 new messages