__slots__ vs __dict__
Marcus von Appen
mva at sysfault.org
Thu May 13 12:20:14 EDT 2004
Andrew Bennetts <andrew-pythonlist at puzzling.org> writes:
[...]
> Now your example runs just fine (i.e. the script terminates normally, and
> nothing happens). I still don't see any error.
I thought you would inspect the objects yourself. Let me show you another (now
working) example, which will explain it:
------
class DictClass (object):
test = "DictTest"
def __init__ (self):
pass
class SlotClass (object):
__slots__ = "test"
def __init__ (self):
self.test = "SlotTest"
def print_obj (obj):
# inspect .test and show the object attributes
print obj.test
print dir (obj)
# bind new attribute and inspect the object attributes
obj.new_test = "Test"
print obj.new_test
print dir (obj)
print "------"
return
if __name__ == "__main__":
dict_obj = DictClass ()
slot_obj = SlotClass ()
print_obj (dict_obj)
print_obj (slot_obj)
---
You will get something like the following output:
----------------
DictTest
['__class__', '__delattr__', '__dict__', ....., '__weakref__', 'test']
Test
['__class__', '__delattr__', '__dict__', ...., '__weakref__', 'new_test',
'test']
------
SlotTest
['__class__', '__delattr__', ...., '__slots__', '__str__', 'test']
Traceback (most recent call last):
File "foo.py", line 31, in ?
print_obj (slot_obj)
File "foo.py", line 19, in print_obj
obj.new_test = "Test"
AttributeError: 'SlotClass' object has no attribute 'new_test'
----------------
As you will notice, a __slot__ed object/class has no __weakref__ nor __dict__
attribute.
Thus binding new object attributes will fail with an AttributeError.
So let's try it again with using __setattr__ in SlotClass:
class SlotClass (object):
test = "SlotTest"
test2 = "SlotTest2" # just for making a tuple creation easier
__slots__ = test, test2
def __init__ (self):
pass
def __setattr__ (self, name, value):
# create a dict here to add its key to the __slot__ tuple
self.__slots__.__add__ (tuple ((name)))
return
def print_obj (obj):
# inspect .test and show the object attributes
print obj.test
print dir (obj)
# bind new attribute and inspect the object attributes
obj.new_test = "Test"
print obj.new_test
print dir (obj)
print "------"
return
if __name__ == "__main__":
#dict_obj = DictClass ()
slot_obj = SlotClass ()
#print_obj (dict_obj)
print_obj (slot_obj)
----
As you will see, you get an AttributeError again.tuple ((name))was not
concatenated to __slots__.
I think that should explain enough about the advantage and disadvantage of
__slots__ here.
(And why do you keep
> putting a redundant return at the end of your functions?)
I'm used to it :-).
> Are you sure this is the same code that you get a crash with? What version
> of Python are you using? (I've tested with 2.2.3 and 2.3.3).
No, I put messy code without _really_ thinking about it in my first post.
I did not realize that self.__slots__ = self._slots in __setattr__ will end
up in a recursion...
Regards
Marcus
--
We don't understand the software, and sometimes we don't understand the
hardware, but we can *see* the blinking lights!
More information about the Python-list
mailing list