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

method names in __slots__ ??

P: n/a
I have stumbled across some class definitions which include all/most
method names in a __slots__ "declaration". A cut-down and disguised
example appears at the end of this posting.

Never mind the __private_variables and the getter/setter approach, look
at the list of methods in the __slots__.

I note that all methods in an instance of a slotted class are read-only
irrespective of whether their names are included in __slots__ or not:
Given a = Adder(),
a.tally = 0
gets AttributeError: 'Adder' object attribute 'tally' is read-only
a.notinslots = 1
gets AttributeError: 'Adder' object attribute 'notinslots' is read-only

So is there some magic class-fu going down here, or is this just a
waste of memory space in the instances?

=== example ===
# class with method names in __slots__

class Adder(object):

__slots__ = [
# methods
'__init_',
'get_foo',
'get_value',
'set_foo',
'tally',
# private variables
'__foo',
'__value',
# public variables
'bar',
'zot',
]

def __init__(self, start=0):
self.__value = start
self.__foo = 666
self.bar = None
self.zot = 42

def tally(self, amount):
self.__value += amount

def get_value(self):
return self.__value

def set_foo(self, arg):
self.__foo = arg

def get_foo(self):
return self.__foo

def notinslots(self):
pass
=== end of example ===

Dec 25 '06 #1
Share this Question
Share on Google+
3 Replies


P: n/a
John Machin wrote in news:1167008799.074885.250770@
73g2000cwn.googlegroups.com in comp.lang.python:
Given a = Adder(),
a.tally = 0
gets AttributeError: 'Adder' object attribute 'tally' is read-only
a.notinslots = 1
gets AttributeError: 'Adder' object attribute 'notinslots' is read-only

So is there some magic class-fu going down here, or is this just a
waste of memory space in the instances?
Haven't you, with your 2 examples above, answered your own question ?

Clearly from your example it doesn't make any difference if you add
a class attribute to the slots, one way or another its as if you
hadn't put it in there in the first place.

This will give the same error, which shows its about class attributes
and not just methods:

class Adder(object):

__slots__ = [
'class_name'
]

class_name = 3
a = Adder()

a.class_name = 2

It would seem that the interpreter removes any names it finds as class
attribute names from the list it finds in __slots__ before it creates
the instance.

Of course if my guessing above isn't good enough, we could look at
the documentation:

http://docs.python.org/ref/slots.html#l2h-218

__slots__ are implemented at the class level by creating descriptors
(3.4.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.

So its that the __slots__ assignment makes the descriptors and then the
subsiquent method defenitions and class attribute bindings remove them.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Dec 25 '06 #2

P: n/a
Rob Williscroft wrote:
John Machin wrote in news:1167008799.074885.250770@
73g2000cwn.googlegroups.com in comp.lang.python:
Given a = Adder(),
a.tally = 0
gets AttributeError: 'Adder' object attribute 'tally' is read-only
a.notinslots = 1
gets AttributeError: 'Adder' object attribute 'notinslots' is read-only

So is there some magic class-fu going down here, or is this just a
waste of memory space in the instances?

Haven't you, with your 2 examples above, answered your own question ?
No.
>
Clearly from your example it doesn't make any difference if you add
a class attribute to the slots, one way or another its as if you
hadn't put it in there in the first place.
Clearly? Not so. It takes up memory. A list of 1 million Adder
instances takes up about 68 Mb (Python 2.5 on Windows XP). With the
method names removed from the __slots__, it takes only about 44 Mb.
[For comparison: with no __slots__ at all, it takes about 180 Mb]
>
This will give the same error, which shows its about class attributes
and not just methods:

class Adder(object):

__slots__ = [
'class_name'
]

class_name = 3
a = Adder()

a.class_name = 2

It would seem that the interpreter removes any names it finds as class
attribute names from the list it finds in __slots__ before it creates
the instance.
It doesn't seem so to me. If it did that, the memory usage would not
increase.
>
Of course if my guessing above isn't good enough, we could look at
the documentation:

http://docs.python.org/ref/slots.html#l2h-218

__slots__ are implemented at the class level by creating descriptors
(3.4.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 have read that, before I posted. Asides:
(1) It would be useful if it stated the empirically determined fact
that the result is that the class attribute is thusly made read-only.
(2) The second sentence is not a model of clarity.

In any case I can't see how the paragraph gives any support for your
next statement:
>
So its that the __slots__ assignment makes the descriptors and then the
subsiquent method defenitions and class attribute bindings remove them.
Errrmmm ... if the descriptors are removed, how is it that the
behaviour is read-only?

Cheers,
John

Dec 25 '06 #3

P: n/a
John Machin wrote in
news:11*********************@n51g2000cwc.googlegro ups.com in
comp.lang.python:
Rob Williscroft wrote:
>John Machin wrote in news:1167008799.074885.250770@
73g2000cwn.googlegroups.com in comp.lang.python:
Given a = Adder(),
a.tally = 0
gets AttributeError: 'Adder' object attribute 'tally' is read-only
a.notinslots = 1
gets AttributeError: 'Adder' object attribute 'notinslots' is
read-only

So is there some magic class-fu going down here, or is this just a
waste of memory space in the instances?

Haven't you, with your 2 examples above, answered your own question ?

No.
>>
Clearly from your example it doesn't make any difference if you add
a class attribute to the slots, one way or another its as if you
hadn't put it in there in the first place.

Clearly? Not so. It takes up memory. A list of 1 million Adder
instances takes up about 68 Mb (Python 2.5 on Windows XP). With the
method names removed from the __slots__, it takes only about 44 Mb.
[For comparison: with no __slots__ at all, it takes about 180 Mb]
68 - 44 = 24
24 / 4 = 6

So thats 6 pointers for 5 methods, probably 5 pointers and and 4 bytes
round up to the nearest allocation unit.

So the slots in the instance are staying arround, even though they
are no longer accesable (see below).

[snip]
It would seem that the interpreter removes any names it finds as
>class attribute names from the list it finds in __slots__ before it
creates the instance.

It doesn't seem so to me. If it did that, the memory usage would not
increase.
It was a guess, and an incorrect guess, but thats why I quoted the
docs below.
>
>>
Of course if my guessing above isn't good enough, we could look at
the documentation:

http://docs.python.org/ref/slots.html#l2h-218

__slots__ are implemented at the class level by creating descriptors
(3.4.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 have read that, before I posted. Asides:
(1) It would be useful if it stated the empirically determined fact
that the result is that the class attribute is thusly made read-only.
(2) The second sentence is not a model of clarity.

In any case I can't see how the paragraph gives any support for your
next statement:
>>
So its that the __slots__ assignment makes the descriptors and then
the subsiquent method defenitions and class attribute bindings remove
them.

Errrmmm ... if the descriptors are removed, how is it that the
behaviour is read-only?
The descriptors are part of the class object, they are removed
when the class attributes are rebound, further rebinding of
the class attributes will work fine:

Adder.tally = 0

They are not assignable in the instance as the class descriptors
that would have forwarded the assignment to the instances slots have
been replaced.

The memory usage is higher because the slots in the instance are
still there even though the descriptors that would allow them to
be assigned have been removed.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Dec 25 '06 #4

This discussion thread is closed

Replies have been disabled for this discussion.