How can we make code like the following emulate the __getattribute__ method inherited from object? I really want to modify the behavior of __getattribute__ but I'd like to begin by just getting the natural behavior.
class Descriptor:
def __get__(*args):
pass
def __set__(*args)
pass
class K:
__getattribute__ = Descriptor()
Yes, we can make
__getattribute__a descriptor! First of all, if a there is an integer member variable namedx, then a descriptor__get__method written forxshould return an integer. Likewise, since__getattribute__is a function, the__get__for__getattribute__will return a function. Initially, let's have__get__return a silly function namedfoo, just so that we can run the program see what's going on:Now, we try the following:
Below are the statements seen on the the console (
stdout):Note that
foodoesn't receive the instance object through the usualselfparameter. Instead,fooreceives ONLY the attribute name'x'Normally, the following two pieces of code produce the same end results:
Let's try running
K.__getattribute__(instance, 'x'):The input to
__get__and the input tofooare actually different from before.As such, we want
__get__to look like the following:If you want the default behavior of
__getattribute__, the following almost works:The Problem of Global Variables
Having
selfbe a global variable inside of the lambda function namedlambyis extremely dangerous. When the lambda function eventually gets called,selfwon't be the sameselfthat existed when the lambda function was defined. Consider the following example:coloris a member variable inside of the lambda functionget_fleece_color. Whenget_fleece_colorwas definedcolorwas"white", but that might change:The output is:
Functions make with the
defkeyword instead oflambdaare equally dangerous.We want to use
selfas it existed at the same timelambywas defined, and not use tehselfvalues which exists whenlambyis called. There are several ways to do this, 3 of which are shown below:Avoid Global Variable Solution 1
Avoid Global Variable Solution 2
Avoid Global Variable Solution 3
Final remarks on the problem of global variables
Solution 2 has a problem in that the signature of the
methodclass constructor might change in a future version of python. Solution 3 is my favorite, but feel free to pick your own.Inheritance
Inheritance works just fine:
The console output is:
Why make
__getattribute__a descriptor instead of overriding__getattribute__?One advantage is that we have access to the class parameter passed into descriptor
__get__methods. Note that__get__is called as__get__(descriptor, Kinstance, Kclass)We don't normally have direct access toKclass, but if__getattribute__is written as a descriptor, then it can accessKclass