I have this code:
from typing import Callable, Any
class Test(classmethod):
def __init__(self, f: Callable[..., Any]):
super().__init__(f)
def __get__(self,*args,**kwargs):
print(args) # why out put is (None, <class '__main__.A'>) where form none why no parameter 123
# where was it called
return super().__get__(*args,**kwargs)
class A:
@Test
def b(cls,v_b):
print(cls,v_b)
A.b(123)
Why the output is (None, <class '__main__.A'>)
? Where did None
come form and why is it not the parameter 123, which is the value I called it with?
The __get__
method is called when the method b
is retrieved from the A
class. It has nothing to do with the actual calling of b
.
To illustrate this, separate the access to b
from the actual call of b
:
print("Getting a reference to method A.b")
method = A.b
print("I have a reference to the method now. Let's call it.")
method()
This results in this output:
Getting a reference to method A.b
(None, <class '__main__.A'>)
I have a reference to the method now. Let's call it.
<class '__main__.A'> 123
So you see, it is normal that the output in __get__
does not show anything about the argument you call b
with, because you haven't made the call yet.
The output None, <class '__main__.A'>
is in line with the Python documentation on __get__
:
object.__get__(self, instance, owner=None)
Called to get the attribute of the owner class (class attribute access) or of an instance of that class (instance attribute access). The optional owner argument is the owner class, while instance is the instance that the attribute was accessed through, or
None
when the attribute is accessed through the owner.
In your case you are using it for accessing an attribute (b
) of a class (A
) -- not of an instance of A
-- so that explains the instance
argument is None
and the owner
argument is your class A
.
The second output, made with print(cls,v_b)
, will print <class '__main__.A'>
for cls
, because that is what happens when you call class methods (as opposed to instance methods). Again, from the documentation:
When a class attribute reference (for class
C
, say) would yield a class method object, it is transformed into an instance method object whose__self__
attribute isC
.
Your case is described here, where A
is the class, and so the first parameter (which you called cls
) will get as value A
.