0

At a little bit of a loss here. I'm attempting to decorate all methods of a class, and using the solution here. I feel like I have all the pieces (see below) yet when I initialize the class/call its methods, nothing happens.

As a toy example, I've got the function decorator

def my_decorator(func):
    def wrapper(*args):
        print("Something is happening before the function is called.")
        return func(*args)
        print("Something is happening after the function is called.")
    return wrapper

and the class decorator

def for_all_methods(decorator):
    import inspect
    def decorate(cls):
        for name, fn in inspect.getmembers(cls, inspect.ismethod):
            print(name, fn)
            setattr(cls, name, decorator(fn))
        return cls
    return decorate

and the toy class

@for_all_methods(my_decorator)
class Car:
    def __init__(self):
        self.wheels = 4
        self.price=20000
        self.mileage = 0
    
    def drive(self, miles):
        self.mileage += miles
    
    def depreciate(self):
        self.price-=0.1*self.mileage

yet when I initialize the class

c = Car()

or call its methods, they aren't decorated. What gives? I feel like I must be missing something trivial.

ahalev
  • 1

2 Answers2

3

inspect.ismethod checks for bound method objects - the kind of thing you get from Car().drive, not Car.drive. Car.drive is a function object.

The code you were looking at was written for Python 2 only. Methods work a bit differently on Python 2.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • Somehow, it works if I change it to `inspect.isfunction`. I still don't entirely understand, since `for name, fn in inspect.getmembers(Car(), inspect.ismethod): print(name, fn)` prints what I would expect. – ahalev Feb 05 '21 at 21:44
  • 1
    @ahalev: `inspect.getmembers(Car(), ...)` is a very different call from `inspect.getmembers(Car, ...)`. – user2357112 Feb 05 '21 at 21:45
0

Okay, it works if I change inspect.ismethod to inspect.isfunction.

I still don't 100% get it, since

for name, fn in inspect.getmembers(Car(), inspect.ismethod):
     print(name, fn)

prints

__init__ <bound method my_decorator.<locals>.wrapper of <__main__.Car object at 0x7fb577e30cf8>>
depreciate <bound method my_decorator.<locals>.wrapper of <__main__.Car object at 0x7fb577e30cf8>>
drive <bound method my_decorator.<locals>.wrapper of <__main__.Car object at 0x7fb577e30cf8>>

as I would expect.

Edit: user2357112 supports Monica clarified here.

ahalev
  • 1