【问题标题】:Why does getattr does not work when a function had a decorator为什么当函数有装饰器时 getattr 不起作用
【发布时间】:2021-07-17 19:07:14
【问题描述】:

我有以下代码 sn-p,它有两个方法 func_norule() 和 func_with_rule()。 func_with_rule() 方法被 @rule 修饰,而 func_norule() 没有任何修饰符。

当我使用 getattr 函数时 fn = getattr(self, 'func_norule') 返回函数 fn = getattr(self, 'func_with_rule') 返回 None .

为什么在使用装饰器和不使用装饰器时会有不同的行为? 有什么办法解决这个问题?

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()

【问题讨论】:

  • 装饰器根本不是这样工作的。它应该返回一个函数(新的、经过修饰的函数)来替换未修饰的函数。你的只是没有明确返回,所以它返回None

标签: python python-decorators


【解决方案1】:

那是因为你没有在你的装饰器中绑定self。您可以更改您的装饰器,以便将 self 参数传递给您的装饰方法:

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)

现在,当你这样做时

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

输出

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

【讨论】:

  • 感谢@enzo 这个解决方案对我有用!
猜你喜欢
  • 1970-01-01
  • 2018-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 2017-04-02
相关资源
最近更新 更多