[Python-Dev] PEP 252 comment
Michael McLay
mclay@nist.gov
Mon, 5 Nov 2001 12:54:10 -0500
The potential for optimizing the new class/type sytem in Python can be
improved by adding an additional constraint to the name lookup rules[1].
This new constrain only apply to the new name lookup rules for types that
include __slots__ definitions so the change should not break backward
compatibility.
- Any name defined by __slot__ is not allowed as a key in the type
dict. This rule would eliminate special type attribute names, like
__dict__ and __class__, from the names allowed in __slots__.
The constraint would also make it illegal to injected a name into the type
dictionary from outside the class definition if that name is one of the
names in _slots__.
In the following example the costraint would allow the assignment to B.d, but
not the assignment to B.b. The assignment of 'c=5' would trigger a TypeError
because the c is defined in __slots__. The '__dict__' in __slots__ would
also trigger a type error because it is a special attribute name that is
defined for all types.
>>> class B(object):
a = 3
c = 5
__slots__ = ['b', '__dict__' , 'c']
def __init__(self):
self.b = 4
>>> B.d = 'fish'
>>> b = B()
>>> b.b
4
>>> b.d
'fish'
>>> B.b = 3.2
>>> b.b
3.2000000000000002
>>> b.b = 55
Traceback (most recent call last):
File "<pyshell#29>", line 1, in ?
b.b = 55
AttributeError: 'B' object attribute 'b' is read-only
>>>
The rule eliminates the need to look in the type dictionary if the name is
defined in __slots__. The cryptic AttributeError message in the example
would never occur.
A slightly more restrictive rule would extend the constraint to eliminate any
addition of names to the type dict from outside of the class definition.
This additional constraint would make the assignment to B.d illegal in the
previous example. This rule would make it possible to know the complete list
of all names that could be referenced by an object of the given type.
[1] From http://python.sourceforge.net/peps/pep-0252.html
In the more complicated case, there's a conflict between names
stored in the instance dict and names stored in the type dict.
If both dicts have an entry with the same key, which one should
we return? Looking at classic Python for guidance, I find
conflicting rules: for class instances, the instance dict
overrides the class dict, *except* for the special attributes
(like __dict__ and __class__), which have priority over the
instance dict.
- I resolved this with the following set of rules, implemented in
PyObject_GenericGetAttr():
1. Look in the type dict. If you find a *data* descriptor, use
its get() method to produce the result. This takes care of
special attributes like __dict__ and __class__.
2. Look in the instance dict. If you find anything, that's it.
(This takes care of the requirement that normally the
instance dict overrides the class dict.)
3. Look in the type dict again (in reality this uses the saved
result from step 1, of course). If you find a descriptor,
use its get() method; if you find something else, that's it;
if it's not there, raise AttributeError.