对于python来说,一切皆对象
函数引用
函数可以被赋值给一个变量
def print_content(data):
print(f"传来的参数是:{data}")
print("print_content的内存地址是:", print_content)
fun_name = print_content
print("fun_name的内存地址是:", fun_name)
fun_name("函数被赋值给了fun_name")
执行结果为:
print_content的内存地址是: <function print_content at 0x000002453131EC20>
fun_name的内存地址是: <function print_content at 0x000002453131EC20>
传来的参数是:函数被赋值给了fun_name
闭包函数
闭包函数,函数中的函数,即在某个函数中,定义一个函数,该函数被称为当前函数的闭包函数;
- 闭包的内部函数中,对外部作用域的变量进行引用,但无法修改外部函数的局部变量
- 闭包可以保存当前的运行环境
示例:
def student_grade(grade):
print(f"以下是{grade}年级的学生:")
def student_info(name, gender):
print(f"姓名:{name}, 性别:{gender}, 年级:{grade}")
return student_info
grade3 = student_grade(3)
grade3("张三", "男")
grade3("李四", "男")
grade3("林婉婉", "女")
执行结果为:
以下是3年级的学生:
姓名:张三, 性别:男, 年级:3
姓名:李四, 性别:男, 年级:3
姓名:林婉婉, 性别:女, 年级:3
装饰器
装饰器其实也是函数,只是对已有的函数进行装饰
以下以统计函数执行时间为例子进行讲解。
函数作为参数
装饰器的原理实际上是将函数作为一个对象,以传参的方式传递给另外一个函数
import datetime
def count_exe_time(func):
start_time = datetime.datetime.now()
func()
end_time = datetime.datetime.now()
print(f"执行{func}的时间为:{end_time-start_time}")
def sum():
index = 10000
result = 0
while index >= 0:
result += index
index -= 1
print(f"相加结果为:{result}")
count_exe_time(sum)
执行结果:
相加结果为:50005000
执行<function sum at 0x000001D89831F760>的时间为:0:00:00.000996
从示例中可以看出,count_exe_time(func)是用来计算函数func执行时需要的时间,要计算出sum()函数的执行时间,需要将sum()的函数名作为参数传给count_exe_time函数,使用时,是调用count_exe_time函数,可读性差,毕竟每次去看看执行了哪个函数,都只能根据参数去识别。
装饰器的简单使用
为了解决 函数作为参数的问题,提高代码的可读性、维护和管理,python提供了装饰器进行使用。
装饰器注意要点:
- 作为装饰器的函数,其参数最好只有1位,作为被装饰函数的参数。
- 装饰器内需要有个内包函数,在执行了被装饰函数后,必须返回该内包函数
- 如果某个函数需要使用对应的装饰器,只需要在对应的函数定义前一行加上:
@装饰器名称
- 装饰器可能会装饰多个函数,所以对于被装饰函数的参数是不确定的,在闭包函数中,参数最好使用
(*args, **kwargs)
(只是在闭包函数中,不是被装饰的函数)
不带参数的装饰器
import datetime
# 定义一个函数,作为装饰器,只传递一个参数
def count_exe_time(func):
# 定义一个闭包函数,计算函数执行时间
def timer():
start_time = datetime.datetime.now()
func()
end_time = datetime.datetime.now()
print(f"执行{func}的时间为:{end_time-start_time}")
# 返回闭包函数,注意只有函数名,没有括号
return timer
# 装饰器使用格式:@函数名
@count_exe_time
def sum():
index = 10000
result = 0
while index >= 0:
result += index
index -= 1
print(f"相加结果为:{result}")
# 直接根据对应的函数进行调用,不用通过装饰器函数来调用
sum()
执行结果为:
相加结果为:50005000
执行<function sum at 0x0000021DC0F3F760>的时间为:0:00:00.000999
带参数的装饰器
import datetime
def count_exe_time(func):
# 为了兼容sum()和sum(num)这2个函数,将闭包函数及其函数内的func函数调用,均设置传入参数为不定长参数
def inner(*args, **kwargs):
start_time = datetime.datetime.now()
# 被装饰的函数调用,参数为不定长参数
func(*args, **kwargs)
end_time = datetime.datetime.now()
print(f"执行{func}的时间为:{end_time-start_time}")
return inner
@count_exe_time
def sum():
index = 10000
result = 0
while index >= 0:
result += index
index -= 1
print(f"相加结果为:{result}")
@count_exe_time
def sum_with_params(num):
index = num
result = 0
while index >= 0:
result += index
index -= 1
print(f"相加结果为:{result}")
sum()
print("--------------------------")
sum_with_params(8000)
执行结果为:
相加结果为:50005000
执行<function sum at 0x000002199017F760>的时间为:0:00:00.001000
--------------------------
相加结果为:32004000
执行<function sum_with_params at 0x000002199017F9A0>的时间为:0:00:00.000999