Python 将decorators类应用于另一个类的方法

Python 将decorators类应用于另一个类的方法,python,oop,decorator,Python,Oop,Decorator,我正在学习decorators,我正在尝试将一个简单的decorator类应用到另一个类的方法中,以便于理解和教育 class decorators(): def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): print(f'this method has been decorated') return self.fu

我正在学习decorators,我正在尝试将一个简单的decorator类应用到另一个类的方法中,以便于理解和教育

class decorators():
    def __init__(self, func):
        self.func = func
    
    def __call__(self, *args, **kwargs):
        print(f'this method has been decorated')
        return self.func(self,*args, **kwargs)

class Users():
    def __init__(self,name,password,age,email):
        self.name = name
        self.password = password
        self.age = age
        self.email = email

    @decorators
    def login(self):
        name = input('Enter your name')
        password = input('Enter your password')
        if name == self.name and password == self.password:
            print("user logged in")
        else:
            print("wrong credentials")

    @decorators
    def show(self):
        print(f'my name is {self.name} and my age is {self.age}')

user1 = Users('John', 'pass', 20, 'john@doe.com')
user1.login()
正如您所看到的,我只是想测试是否可以构建这个decorator类来调用Users类中的任何方法,比如login()和show()。如上所述调用user1.login()时,出现以下错误:

AttributeError                            Traceback (most recent call last)
<ipython-input-98-ed78c0a45454> in <module>
----> 1 user1.login()

<ipython-input-96-759e600a717b> in __call__(self, *args, **kwargs)
      5     def __call__(self, *args, **kwargs):
      6         print(f'this method has been decorated')
----> 7         return self.func(self,*args, **kwargs)
      8 
      9 class Users():

<ipython-input-96-759e600a717b> in login(self)
     18         name = input('Enter your name')
     19         password = input('Enter your password')
---> 20         if name == self.name and password == self.password:
     21             print("user logged in")
     22         else:

AttributeError: 'decorators' object has no attribute 'name'
AttributeError回溯(最近一次调用)
在里面
---->1 user1.login()
在调用中(self,*args,**kwargs)
5定义调用(self,*args,**kwargs):
6打印(f‘此方法已装饰’)
---->7返回self.func(self、*args、**kwargs)
8.
9类用户():
在登录(自我)
18 name=输入('输入您的姓名')
19密码=输入('输入您的密码')
--->20如果name==self.name和password==self.password:
21打印(“用户登录”)
22.其他:
AttributeError:“装饰器”对象没有属性“名称”

我的想法是,用户实例不会传递给decorator,因此decorator对象没有用户属性“name”。有什么方法可以做到这一点吗?

您正在将
self
传递给
self.func
的第一个参数:
返回self.func(self,*args,**kwargs)
但是
self
是一个
装饰程序
实例,而不是
用户
的实例,因此出现错误

有多种方法可以实现这一点。本质上,当通过

也就是说,函数对象是描述符,它们的
\uuu get\uu
方法部分地将实例应用于自身。因此,使自定义类像函数对象一样工作的最干净的方法是使
装饰器
类成为描述符,复制函数对象的功能:

from types import MethodType
class decorators:
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kwargs):
        print(f'this method has been decorated')
        return self.func(*args, **kwargs)
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        return MethodType(self, obj)
例如:

>>> from types import MethodType
>>> class decorators:
...     def __init__(self, func):
...         self.func = func
...     def __call__(self, *args, **kwargs):
...         print(f'this method has been decorated')
...         return self.func(*args, **kwargs)
...     def __get__(self, obj, objtype=None):
...         if obj is None:
...             return self
...         return MethodType(self, obj)
...
>>> class Foo:
...     def __init__(self):
...         self.bar = 42
...     @decorators
...     def frobnicate(self):
...         return self.bar + 1
...
>>> Foo().frobnicate()
this method has been decorated
43

这可能有助于将
self
传递给
self.func
的第一个参数:
返回self.func(self,*args,**kwargs)
但是
self
是一个
装饰程序
实例,而不是
用户
的实例,因此出现错误“我的想法是,用户实例没有传递给decorator,因此decorator对象没有用户属性的名称;“为什么
decorator
对象会有另一个对象的属性?谢谢大家。我理解为什么会出现这个问题now@Alice_inwonderland实际上,请检查我的编辑,我的意思是将
self
传递给MethodType,而不是在
decorators中使用
self
。\uuuuu调用\uuuuu