使用装饰器时出现TypeError:wrapper()需0参却传入2个的原因排查
装饰器引发TypeError错误解析
错误信息
File "/Users/red/PycharmProjects/general_purpose_object_factory/music.py", line 26, in __call__ self._instance = SpotifyService(access_code) TypeError: wrapper() takes 0 positional arguments but 2 were given Process finished with exit code
相关代码
decorators.py
def debug_printer(func): def wrapper(): print("Hello") func() return wrapper
music.py
import object_factory from decorators import debug_printer class MusicServiceProvider(object_factory.ObjectFactory): def get(self, service_id, **kwargs): return self.create(service_id, **kwargs) class SpotifyService: @debug_printer def __init__(self, access_code): self._access_code = access_code def test_connection(self): print(f'Accessing Spotify with {self._access_code}') class SpotifyServiceBuilder: def __init__(self): print(f"{__class__.__name__}") self._instance = None def __call__(self, spotify_client_key, spotify_client_secret, **_ignored): if not self._instance: access_code = self.authorize( spotify_client_key, spotify_client_secret) self._instance = SpotifyService(access_code) # <<<< LINE 26. !!!!!! return self._instance def authorize(self, key, secret): return 'SPOTIFY_ACCESS_CODE'
问题原因
你的debug_printer装饰器里的wrapper函数没有定义参数,但被装饰的SpotifyService.__init__是实例方法,调用时会自动传入两个参数:self(类实例本身)和access_code(你传入的参数)。当装饰器替换原方法后,调用SpotifyService(access_code)实际是调用wrapper(),但此时传入了两个参数,而wrapper没有接收参数的能力,所以触发参数不匹配的TypeError。
解决方法
修改装饰器,让wrapper能够接收并传递任意参数给原函数:
def debug_printer(func): def wrapper(*args, **kwargs): print("Hello") func(*args, **kwargs) return wrapper
*args会捕获所有位置参数(这里就是self和access_code),**kwargs捕获所有关键字参数(当前场景下没有,但保留可以让装饰器更通用)。- 把捕获到的参数传递给原函数
func,这样原__init__方法就能正常接收所需的参数,完成初始化。
内容的提问来源于stack exchange,提问作者Red Cricket
相关产品推荐
相关产品推荐

