__bases__ misleading error message
marco.buttu at gmail.com
Sun Jan 25 11:30:05 CET 2015
On 25/01/2015 01:55, Terry Reedy wrote:
> 'This situation' being that Someclass.attro works but Someclass().attro
> 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
>>> isinstance(Sub, type)
>>> hasattr(Sub, '__bases__')
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)
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.
> 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()
More information about the Python-list