简体   繁体   中英

Decorating a Python method already decorated with @classmethod which calls another @classmethod

This is a base Python question. I am trying to decorate a @classmethod with my own decorator, my_decorator . The original @classmethod actually calls another @classmethod inside. The problem comes up when calling this inner method because it depends on the cls argument. This would be fine if I could just replace any call like cls.boo() with Foo.boo() if my class is always Foo , but this is obviously not a choice when I write children classes that inherit from Foo . Below is what I am trying to write.

def my_decorator(method):
    def redefined_method(*args, **kwargs):
        print('Starting decorator')
        result = method(args, **kwargs)
        return result
    return redefined_method

class Foo(object):        
    @classmethod
    def boo(cls):
        print('Running from Foo\'s boo')

    @classmethod
    @my_decorator
    def bar(cls):
        print('Running from Foo\'s bar')
        '''
        Replacing the following line with 'Foo.boo()'
        produces no errors when calling `Foo.bar()`, 
        but then we can't run Child's version of the boo method.
        ''' 
        cls.boo()

class Child(Foo):
    @classmethod
    def boo(cls):
        print('Running from Child\'s version of boo')

if __name__ == '__main__':
    Foo.bar()    
    Child.bar()

I expect the following output.

Starting decorator
Running from Foo's bar
Running from Foo\'s boo
Starting decorator
Running from Foo's bar
Running from Child\'s version of boo

Current output.

Starting decorator
Running from Foo's bar
Traceback (most recent call last):
  File "C:\....\dec_example.py", line 29, in <module>
    Foo.bar()    
  File "C:\....\dec_example.py", line 4, in redefined_method
    method(args, **kwargs)
  File "C:\....\dec_example.py", line 21, in bar
    cls.boo()
AttributeError: 'tuple' object has no attribute 'boo'

I tried switching the order of @classmethod and @my_decorator but it still doesn't work and produces the following stacktrace.

Starting decorator
Traceback (most recent call last):
  File "C:\....\dec_example.py", line 29, in <module>
    Foo.bar()    
  File "C:\....\dec_example.py", line 4, in redefined_method
    method(args, **kwargs)
TypeError: 'classmethod' object is not callable

You forgot to unpack args :

def my_decorator(method):
    def redefined_method(*args, **kwargs):
        print('Starting decorator')
        method(args, **kwargs)
        # here ^, no star!
    return redefined_method

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM