Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

125
Views
Some problems about Python inherited classmethod

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?

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

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 is C.

Your case is described here, where A is the class, and so the first parameter (which you called cls) will get as value A.

over 4 years ago · Santiago Trujillo Report

0

You can apply multiple decorators on the same function, for example,

  • first (and outer) decorator could be a classmethod
  • and the second (doing your stuff) could define a wrapper, where you could accept your arguments as usual
In [4]: def test_deco(func):
   ...:     def wrapper(cls, *args, **kwds):
   ...:         print("cls is", cls)
   ...:         print("That's where 123 should appear>>>", args, kwds)
   ...:         return func(cls, *args, **kwds)
   ...: 
   ...:     return wrapper
   ...: 
   ...: 
   ...: class A:
   ...:     @classmethod
   ...:     @test_deco
   ...:     def b(cls, v_b):
   ...:         print("That's where 123 will appear as well>>>", v_b)
   ...: 
   ...: 
   ...: A.b(123)
cls is <class '__main__.A'>
That's where 123 should appear>>> (123,) {}
That's where 123 will appear as well>>> 123

In [5]: 

It's too much trouble to use two at a time i want only use one like it

It is possible to define a decorator applying a couple of other decorators:

def my_super_decorator_doing_everything_at_once(func):
    return classmethod(my_small_decorator_doing_almost_everything(func))

That works because decorators notation

@g
@f
def x(): ...

is a readable way to say

def x(): ...
x = g(f(x))
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!