Python的装饰器本质上就是一个函数的调用与函数句柄的返回,并没有什么非常特别的特性。只不过其加了一个语法糖:
@
基本规律基础
1. 将函数看作object
也可以看作是函数可以有别名,但是本质上是将函数看作object。
代码:
# Python program to illustrate functions
# can be treated as objects
def shout(text):
return text.upper()
print(shout('Hello'))
yell = shout #注意这里给shout加了别名
print(yell('Hello'))
输出:
HELLO
HELLO
2. 将函数作为参数进行传递
代码:
# Python program to illustrate functions
# can be passed as arguments to other functions
def shout(text):
return text.upper()
def whisper(text):
return text.lower()
def greet(func):
# storing the function in a variable
greeting = func("""Hi, I am created by a function passed as an argument.""")
print (greeting)
greet(shout)
greet(whisper) #whisper作为参量输入
输出:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT.
hi, i am created by a function passed as an argument.
3. 返回函数且带额外参数
代码:
# Python program to illustrate functions
# Functions can return another function
def create_adder(x):
def adder(y):
return x+y
return adder
add_15 = create_adder(15) #这里的add_15的内容包括函数adder及create_adder的参数15
print(add_15(10))
输出:
25
装饰器
有了上面的几个例子作为基础,下一步就是分析装饰器的作用。
装饰器语法:
@gfg_decorator#gfg_decorator是目标函数,即装饰器要加到的那个函数
def hello_decorator():
print("Gfg")
'''Above code is equivalent to -
def hello_decorator():
print("Gfg")
hello_decorator = gfg_decorator(hello_decorator)'''
一个不用装饰器但是实现装饰器功能的简单方法:
代码:
# defining a decorator
def hello_decorator(func):
# inner1 is a Wrapper function in
# which the argument is called
# inner function can access the outer local
# functions like in this case "func"
def inner1():
print("Hello, this is before function execution")
# calling the actual function now
# inside the wrapper function.
func()
print("This is after function execution")
return inner1
# defining a function, to be called inside wrapper
def function_to_be_used():
print("This is inside the function !!")
# passing 'function_to_be_used' inside the
# decorator to control its behaviour
function_to_be_used = hello_decorator(function_to_be_used)#这里还是用function_to_be_used 这个名字,本质上可以换任何名字都可以,这里是用装饰器的意义所在,即还是用之前的名字就,这样从形式上就为原来的代码增加新的功能。但是这么写很麻烦,那就有了装饰器
function_to_be_used2 = hello_decorator(function_to_be_used)#更改了新的名字,但是和没改名字有一样的功能。
# calling the function
function_to_be_used()
function_to_be_used2()
结果:
Hello, this is before function execution
This is inside the function !!
This is after function execution
Hello, this is before function execution
This is inside the function !!
This is after function execution
那为了解决上述写法问题,就采用装饰器。
例子
# importing libraries
import time
import math
# decorator to calculate duration
# taken by any function.
def calculate_time(func):
# added arguments inside the inner1,
# if function takes any arguments,
# can be added like this.
def inner1(*args, **kwargs):
# storing time before function execution
begin = time.time()
func(*args, **kwargs)
# storing time after function execution
end = time.time()
print("Total time taken in : ", func.__name__, end - begin)
return inner1
# this can be added to any function present,
# in this case to calculate a factorial
@calculate_time#装饰器的意义就在于保持了函数原名
def factorial(num):
# sleep 2 seconds because it takes very less time
# so that you can see the actual difference
time.sleep(2)
print(math.factorial(num))
# calling the function.
factorial(10)
上面要特别注意的是,如果inner1
函数里不是func(*args, **kwargs)
,是func()
的话,程序报错,因为factorial(num)
函数带有参数。
反过来,如果factorial
不带参数,而inner1
函数里仍然是带参数的func(*args, **kwargs)
,则不会报错。
带有返回值的装饰器
代码:
def hello_decorator(func):
def inner1(*args, **kwargs):#方便后续传入参数
print("before Execution")
# getting the returned value
returned_value = func(*args, **kwargs)
print("after Execution")
# returning the value to the original frame
return returned_value
return inner1
# adding decorator to the function
@hello_decorator
def sum_two_numbers(a, b):
print("Inside the function")
return a + b
a, b = 1, 2
# getting the value through return of the function
print("Sum =", sum_two_numbers(a, b))