我有一个处理对服务器的API调用的类。该类中的某些方法要求用户登录。由于会话可能会用完,因此我需要一些功能,以便在会话超时后重新登录用户。我的想法是使用装饰器。如果我这样尝试
class Outer_Class():
class login_required():
def __init__(self, decorated_func):
self.decorated_func = decorated_func
def __call__(self, *args, **kwargs):
try:
response = self.decorated_func(*args, **kwargs)
except:
print('Session probably timed out. Logging in again ...')
args[0]._login()
response = self.decorated_func(*args, **kwargs)
return response
def __init__(self):
self.logged_in = False
self.url = 'something'
self._login()
def _login(self):
print(f'Logging in on {self.url}!')
self.logged_in = True
#this method requires the user to be logged in
@login_required
def do_something(self, param_1):
print('Doing something important with param_1')
if (): #..this fails
raise Exception()
我得到一个错误。 AttributeError: 'str' object has no attribute '_login'
为什么我没有对通过* args移交的Outer_Class-instance的引用?有没有其他方法可以获取实例的引用?
找到了答案How to get instance given a method of the instance?,但是装饰函数似乎没有引用它自己的实例。
当Im在类之外使用装饰器功能时,它可以正常工作。这样就可以解决问题,但是我想知道是否可以通过这种方式解决问题。
答案 0 :(得分:1)
问题在于,将对象作为第一个隐藏参数传递的魔力仅适用于非静态方法。当装饰器返回不是功能的自定义可调用对象时,它永远不会收到在调用中丢失的调用对象。因此,当您尝试调用修饰的函数时,只能在param_1
的位置传递self
。您遇到第一个异常do_something() missing 1 required positional argument: 'param_1'
,陷入except
区块并收到错误。
您仍然可以将装饰器绑定到类上,但是必须具有self
魔术功能:
class Outer_Class():
def login_required(decorated_func):
def inner(self, *args, **kwargs):
print("decorated called")
try:
response = decorated_func(self, *args, **kwargs)
except:
print('Session probably timed out. Logging in again ...')
self._login()
response = decorated_func(self, *args, **kwargs)
return response
return inner
...
#this method requires the user to be logged in
@login_required
def do_something(self, param_1):
print('Doing something important with param_1', param_1)
if (False): #..this fails
raise Exception()
您可以成功完成以下操作:
>>> a = Outer_Class()
Logging in on something!
>>> a.do_something("foo")
decorated called
Doing something important with param_1
答案 1 :(得分:0)
您拥有的命令
args[0]._login()
except
中的。由于args[0]
是一个字符串,并且没有_login
方法,因此您会看到问题中提到的错误消息。