Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't __bases__ accessible in the class body?

Class objects have a __bases__ (and a __base__) attribute:

>>> class Foo(object):
...     pass
... 
>>> Foo.__bases__
(<class 'object'>,)

Sadly, these attributes aren't accessible in the class body, which would be very convenient for accessing parent class attributes without having to hard-code the name:

class Foo:
    cls_attr = 3

class Bar(Foo):
    cls_attr = __base__.cls_attr + 2
    # throws NameError: name '__base__' is not defined

Is there a reason why __bases__ and __base__ can't be accessed in the class body?

(To be clear, I'm asking if this is a conscious design decision. I'm not asking about the implementation; I know that __bases__ is a descriptor in type and that this descriptor can't be accessed until a class object has been created. I want to know why python doesn't create __bases__ as a local variable in the class body.)

like image 620
Aran-Fey Avatar asked May 27 '19 07:05

Aran-Fey


People also ask

What is __ dict __ in Python?

All objects in Python have an attribute __dict__, which is a dictionary object containing all attributes defined for that object itself. The mapping of attributes with its values is done to generate a dictionary.

How do you access the attributes of an object in Python?

Attributes of a class can also be accessed using the following built-in methods and functions : getattr() – This function is used to access the attribute of object. hasattr() – This function is used to check if an attribute exist or not. setattr() – This function is used to set an attribute.

Which keyword is used to get access to the attributes and methods of the class in Python?

The self keyword is used to access the attributes and methods of the class. self just represents an instance of the class.

How do you get data from an object in Python?

Python getattr() function is used to get the value of an object's attribute and if no attribute of that object is found, default value is returned. Basically, returning the default value is the main reason why you may need to use Python getattr() function.


Video Answer


2 Answers

I want to know why python doesn't create __bases__ as a local variable in the class body

As you know, class is mostly a shortcut for type.__new__() - when the runtime hits a class statements, it executes all statements at the top-level of the class body, collects all resulting bindings in a dedicated namespace dict, calls type() with the concrete metaclass, the class name, the base classes and the namespace dict, and binds the resulting class object to the class name in the enclosing scope (usually but not necessarily the module's top-level namespace).

The important point here is that it's the metaclass responsabilty to build the class object, and to allow for class object creation customisations, the metaclass must be free to do whatever it wants with its arguments. Most often a custom metaclass will mainly work on the attrs dict, but it must also be able to mess with the bases argument. Now since the metaclass is only invoked AFTER the class body statements have been executed, there's no way the runtime can reliably expose the bases in the class body scope since those bases could be modified afterward by the metaclass.

There are also some more philosophical considerations here, notably wrt/ explicit vs implicit, and as shx2 mentions, Python designers try to avoid magic variables popping out of the blue. There are indeed a couple implementation variables (__module__ and, in py3, __qualname__) that are "automagically" defined in the class body namespace, but those are just names, mostly intended as additional debugging / inspection informations for developers) and have absolutely no impact on the class object creation nor on its properties, behaviour and whatnots.

As always with Python, you have to consider the whole context (the execution model, the object model, how the different parts work together etc) to really understand the design choices. Whether you agree with the whole design and philosophy is another debate (and one that doesn't belong here), but you can be sure that yes, those choices are "conscious design decisions".

like image 170
bruno desthuilliers Avatar answered Oct 21 '22 00:10

bruno desthuilliers


I am not answering as to why it was decided to be implemented the way it was, I'm answering why it wasn't implemented as a "local variable in the class body":

Simply because nothing in python is a local variable magically defined in the class body. Python doesn't like names magically appearing out of nowhere.

like image 25
shx2 Avatar answered Oct 20 '22 22:10

shx2