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

Reply via email to