Python装饰器深入理解

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))
  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值