装饰器问题
想问一下为什么下面第一种情况是OK的,第二种就会报错呢第一种
class Logging:
def __init__(self, func):
self.func = func
def __call__(self):
print(f"{self.func.__name__}()")
self.func()
@Logging
def say():
print("hello")
say()
say()
hello
第二种
class Logging:
def __init__(self, func, level="INFO"):
self.func = func
self.level = level
def __call__(self):
print(f"[{self.level}: {self.func}()]")
self.func()
@Logging(level="ERROR")
def say():
print("hello")
say()
Traceback (most recent call last):
File "C:\Users\JiJing\Desktop\test.py", line 10, in <module>
@Logging(level="ERROR")
TypeError: Logging.__init__() missing 1 required positional argument: 'func'
本帖最后由 tommyyu 于 2022-11-9 18:42 编辑
原来的代码相当于 say = Logging(level = "ERROR")(say),此时因为 level 参数和 func 参数分批传入,python 就会报错。如果想要实现这种效果,可以这样写class Logging:
def __init__(self, func, level="INFO"):
self.func = func
self.level = level
def __call__(self):
print(f"[{self.level}: {self.func}()]")
self.func()
def temp(level):
def inner(func):
nonlocal level
return Logging(func, level)
return inner
@temp(level = 'INFO')
def say():
print('hello')
say() class Logging:
def __init__(self , level = "INFO"):
self . level = level
def __call__(self , func_name):
def wrapper(* args , ** kwargs):
print(self . level)
return func_name(* args , ** kwargs)
return wrapper
@Logging("ERROR")
def say():
print("hello")
say() tommyyu 发表于 2022-11-9 16:14
原来的代码相当于 say = Logging(level = "ERROR")(say),此时因为 level 参数和 func 参数分批传入,pytho ...
此时因为 level 参数和 func 参数分批传入,python 就会报错。
:这句话不太理解,什么叫分批传入,是level和func一起传入,python无法分辨的意思吗 dami27 发表于 2022-11-10 09:44
此时因为 level 参数和 func 参数分批传入,python 就会报错。
:这句话不太理解,什么叫分批传入,是le ...
在初始化的时候,应该 Logging(func, level) 这样传参,但是因为装饰器的语法原因,你原来的那个 @Logging(level="ERROR")
def say():
print("hello")这个函数的定义被 Python 解析成了
def say():
print("hello")
say = Logging(level = 'ERROR')(say)此时 Python 就会报错。 jackz007 发表于 2022-11-9 18:21
可是为啥这样也会报错?装饰器的函数引用不是不用特意传入的吗{:10_266:}
class Logging:
def __call__(self, func):
def wrapper():
print(f"{func.__name__}()")
return func()
return func
@Logging
def say():
print("hello")
Traceback (most recent call last):
File "C:\Users\JiJing\Desktop\1.py", line 10, in <module>
def say():
TypeError: Logging() takes no arguments 本帖最后由 jackz007 于 2022-11-10 13:17 编辑
dami27 发表于 2022-11-10 09:47
可是为啥这样也会报错?装饰器的函数引用不是不用特意传入的吗
装饰器类在带和不带参数时,参数的传递约定不同,你只要记住就可以了,不带参数时的被装饰函数是在 __init__() 时传入的。任何时候,装饰器类都不可以少了 __init__() 和 __call__(),一个也不能少!!!
class Logging:
def __init__(self , func):
self . func = func
def __call__(self, * args , ** kwargs):
print(f"{self . func . __name__}()")
return func(* args , ** kwargs)
@Logging
def say():
print("hello")
页:
[1]