On 25/01/2015 01:55, Terry Reedy wrote:
'This situation' being that Someclass.attro works but Someclass().attro
raises...
In other words, if 'Someclass.attro' evaluates to an object ...
then 'Someclass().attro' *normally* evaluates to the same object
I am sorry Terry, but I do not agree, because the word "normally" in
this context does not have any meaning, and instroduces just confusion.
In facts this is exactly the case where "Someclass.attro' evaluates to
an object" *but* hasattr(Someclass(), 'attro'), as expected, is False.
What do you mean with "normally"?
because attribute lookup on an instance reverts to attribute lookup on
the class and even its super classes
Here's the point. The __bases__ attribute is defined by the class type.
So if isinstance(obj, type) is true, then hasattr(obj, '__bases__') is
true. In the OP case:
>>> class Sub: # Python 3
... pass
...
>>> isinstance(Sub, type)
True
>>> hasattr(Sub, '__bases__')
True
But Sub() is not an instance of type (because Sub is not a subclass of
type), and so Sub() does not have to get the attributes, like __bases__,
from type, and here's we are:
>>> foo = Sub()
>>> isinstance(foo, type)
False
>>> foo.__bases__
Traceback (most recent call last):
...
AttributeError: 'Sub' object has no attribute '__bases__'
In other words, speaking about the lookup machinery, because '__bases__'
is not in foo.__dict__ Python looks for __bases__ in Sub.__dict__, but
it does not found it. So it looks in the Sub bases, and we went back to
the point: Sub is an instance of type, not a subclass of type.
Someclass.__bases__
is special; it is not listed by dir(Someclass), and it is not accessible
via an instance.
In my point of view no attribute is special (maybe just a descriptor is
a bit special, in some ways). To undestand what happens in these
situations, we do not have to give a special meaning to the attribute.
Given `obj.attr`, we just have to know what kind of object is `obj`:
usually, like in this case, we have to differentiate between classes and
non-classes objects. In fact __bases__ is not listed by dir(Sub) because
Sub is a class, and the distinction between classes and non-classes
objects matters, especially for dir()
--
Marco Buttu
--
https://mail.python.org/mailman/listinfo/python-list