python中@的用法
@是一个装饰器,针对函数,起调用传参的作用。
有修饰和被修饰的区别,‘@function’作为一个装饰器,用来修饰紧跟着的函数(可以是另一个装饰器,也可以是函数定义)。
文章目录
代码1:修饰函数
def funA(desA):
print("It's funA")
print('---')
print(desA)
desA()
print('---')
@funA
def funC():
print("It's funC")
结果1
It's funA
---------
<function funC at 0x7f9667abadc0>
It's funC
---------
分析1
@funA
修饰函数定义funC
,传址funC
给funA
,为了更直观地看参数传递,打印desA,其传的是funC的地址。
执行的时候由上而下,先定义funA,然后运行funA(funC),输出‘It’s funA’。
执行desA()即调用funC,执行funC()。
值得注意的是
直接修饰和执行funA(funC)
的区别
代码1和直接执行funA(funC)
的结果有些出入。
> 代码1
>
It's funA
---------
<function funC at 0x7f9667abadc0>
It's funC
---------
> funA(funC)
>
It's funA
---------
None
Traceback (most recent call last):
File "main.py", line 16, in <module>
funA(funC)
File "main.py", line 8, in funA
desA()
TypeError: 'NoneType' object is not callable
- 为什么
print(desA)
是None
? - 为什么
desA()
报错TypeError: 'NoneType' object is not callable
?
同一个原因:修饰器函数funA
里没有定义返回值。修饰器@funA
接收函数funC
作为参数,在修饰器函数funA
中可以修改参数函数funC
,当我们调用被修饰的函数funC
时,实际上是在执行被修改过的修饰器函数,但在funA
中我们没有返回可调用的函数,默认返回的是None
,所以会出现这两个问题,在funA
中加上返回值(被修饰后的参数)就可以解决。
def funA(desA):
print("It's funA")
print('---')
print(desA)
desA()
print('---')
return desA # <-- missing return statement before
@funA
def funC():
print("It's funC")
funA(funC)
和funA(funC())
差别
funA(funC)
和funA(funC())
是不同的,之前一个笔误将这里的函数调用写成后者。如果我们要执行funA(funC())
,也会报错。
> funA(funC)
>
It's funA
---------
<function funC at 0x7fe2a4f04dc0>
It's funC
---------
> funA(funC())
>
It's funC
It's funA
---------
None
Traceback (most recent call last):
File "main.py", line 17, in <module>
funA(funC())
File "main.py", line 8, in funA
desA()
TypeError: 'NoneType' object is not callable
- 为什么多打印了
It's funC
? - 为什么
print(desA)
是None
? - 为什么
desA()
报错TypeError: 'NoneType' object is not callable
?
这个执行顺序由内向外,先调用funC()
,打印了这一句,然后将调用结果返回传给funA
,在这里传的并不是函数地址,而是函数结果,是一个None
,如果想要不报错,需要在funC
返回一个可调用的函数,这与代码1完全不一样。
代码2:修饰装饰器
def funA(desA):
print("It's funA")
return desA
def funB(desB):
print("It's funB")
return desB
@funB
@funA
def funC():
print("It's funC")
结果2
It's funA
It's funB
分析2
@funB 修饰装饰器@funA,@funA 修饰函数定义def funC(),将funC传给funA,再将funA(funC)传给funB。
执行的时候由上而下,先定义funA、funB,然后运行funB(funA(funC))。
此时desA=funC(),然后funA()输出‘It’s funA’;desB=funA(funC),然后funB()输出‘It’s funB’。