简体   繁体   中英

Why does getattr does not work when a function had a decorator

I have the following code snippet, that has two methods func_norule() and func_with_rule(). The method func_with_rule() is decorated with @rule where as func_norule() do not have any decorator.

When I use the getattr function fn = getattr(self, 'func_norule') returns the function where as fn = getattr(self, 'func_with_rule') returns None.

Any reason why there is a different behaviour when a decorator is used versus when a decorator is not used? Any workaround this problem?

class Student():
    def __init__(self, name, roll_no):
        self.name = name
        self.roll_no = roll_no
    
    ## Decorator function to decorate all the rules function
    def rule(func):
        print(func.__name__)
    
    def func_norule(self):
        #This method works with getattr
        print("func_norule:" + self.name)
    
    @rule
    def func_with_rule(self):
        #This method returns None  with getattr
        print("func_with_rule:" + self.name)
    
    def myFunc2(self):
        fn = getattr(self, 'func_norule')
        fn()
        fn = getattr(self, 'func_with_rule')
        fn()

student = Student('myName', 8)
student.myFunc2()

That's because you're not binding self inside your decorator. You can change your decorator so the self parameter will be passed to your decorated method:

class Student:
    # ...

    def rule(func):
        def _(self, *args, **kwargs):
            print("Before calling", func.__name__)
            result = func(self, *args, **kwargs)
            print("After calling", func.__name__)
            return result            

        return _

    # ...

    @rule
    def func_with_rule(self):
        #This method returns None  with getattr
        print("func_with_rule:" + self.name)

Now, when you do

student = Student('myName', 8)
student.myFunc2()

outputs

func_norule:myName
Before calling func_with_rule
func_with_rule:myName
After calling func_with_rule

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