By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
439,941 Members | 1,789 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 439,941 IT Pros & Developers. It's quick & easy.

__slots__ and class attributes

P: n/a
I'm running into a something unexpected for a new-style class
that has both a class attribute and __slots__ defined. If the
name of the class attribute also exists in __slots__, Python
throws an AttributeError. Is this by design (if so, why)?

class A( object ):
__slots__ = ( 'value', )
value = 1

def __init__( self, value = None ):
self.value = value or A.value

a = A()
print a.value
Traceback (most recent call last):
File "t1.py", line 8, in ?
a = A()
File "t1.py", line 6, in __init__
self.value = value or A.value
AttributeError: 'A' object attribute 'value' is read-only
Nov 3 '05 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Ewald R. de Wit wrote:
I'm running into a something unexpected for a new-style class
that has both a class attribute and __slots__ defined. If the
name of the class attribute also exists in __slots__, Python
throws an AttributeError. Is this by design (if so, why)?

class A( object ):
__slots__ = ( 'value', )
value = 1

def __init__( self, value = None ):
self.value = value or A.value

a = A()
print a.value
Traceback (most recent call last):
File "t1.py", line 8, in ?
a = A()
File "t1.py", line 6, in __init__
self.value = value or A.value
AttributeError: 'A' object attribute 'value' is read-only


Check the documentation on __slots__[1]:

__slots__ are implemented at the class level by creating descriptors
(3.3.2) for each variable name. As a result, class attributes cannot be
used to set default values for instance variables defined by __slots__;
otherwise, the class attribute would overwrite the descriptor assignment.

I agree that the error you get is a bit confusing. I think this has to
do with how the descriptor machinery works. When you write something like
a.value
where a is a class instance, Python tries to invoke something like:
type(a).value.__get__(a)
Here's an example of that, working normallly:

py> class A(object):
.... __slots__ = ['value']
.... def __init__(self):
.... self.value = 1
....
py> a = A()
py> type(a).value
<member 'value' of 'A' objects>
py> type(a).value.__get__
<method-wrapper object at 0x0129A1B0>
py> type(a).value.__get__(a)
1

Now when you add a class attribute called 'value', you overwrite the
descriptor. So when Python tries to do the same thing (because your
definition of __slots__ makes it assume that 'value' is a descriptor),
the descriptor machinery raises an AttributeError:

py> class A(object):
.... __slots__ = ['value']
.... value = 1
....
py> a = A()
py> type(a).value
1
py> type(a).value.__get__
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
AttributeError: 'int' object has no attribute '__get__'

This AttributeError must be somehow caught by the __slots__ machinery
and interpreted to mean that you tried to write to a read-only
attribute. The resulting error message is probably not what you want,
but I don't know the source well enough to figure out whether or not a
better error message could be given.
But why do you want a class level attribute with the same name as an
instance level attribute? I would have written your class as:

class A(object):
__slots__ = ['value']
def __init__(self, value=1):
self.value = value

where the default value you put in the class is simply expressed as a
default value to the __init__ parameter.

Steve

[1]http://docs.python.org/ref/slots.html
Nov 3 '05 #2

P: n/a
Steven Bethard wrote:
But why do you want a class level attribute with the same name as an
instance level attribute? I would have written your class as:

class A(object):
__slots__ = ['value']
def __init__(self, value=1):
self.value = value

where the default value you put in the class is simply expressed as a
default value to the __init__ parameter.


Thanks for your explanation. The reason why I was doing it was
to have class-level defaults, so that one can easily adjust how
new instances will be made. I'm doing it now with capitilized
class attribute names to avoid the name clash.

--
-- Ewald
Nov 4 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.