python基础(01变量&数据类型&运算符)
python基础(02序列共性)
python基础(03列表和元组)
python基础(04字符串&字典)
python基础(05集合set)
python基础(06控制语句)
python基础(07函数)
python基础(08类和对象)
本文主要介绍了函数的特性、闭包以及装饰器的用法,如果理解有困难,多敲几遍也就悟了。
1.函数可以作为变量,赋值给另外一个变量
def add(x):
return x+1
a = add #a指向add函数的地址
print(a) #
print(a(5))# 6
print(add(5))# 6
2.函数可以作为参数传入
def execute(f):
return f(5)
print(execute(add)) #6,相当于add(5)
3.函数对象可以作为返回值
def add(x):
return x+1
def get_add():
return add
c = get_add() #将get_add()的返回值给c了,返回值为add,相当于c=add
print(c) #
print(c(5)) #6
4.嵌套函数里面 调用外层函数时,运行到内层的def语句 仅仅是完成对内层函数的定义,而不会去调用内层函数
x = 99
def f1():
x = 88
def f2():
print(x)
f1() #空
5.局部作用域在函数结束之后会立即消失,但是enclosing 作用域在嵌套函数返回后 仍然有效
x = 99
def f1():
x = 88
def f2():
print(x)
return f2
action = f1()
action() #88
- 就是一个函数
- 在一个内部函数里,存在对外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就认为是闭包,外部函数被认为是闭包函数
- 嵌套函数:外部函数、内部函数
- 内部函数中要使用外部函数的变量
- 外部函数必须还有返回值,返回内部函数名
def out():
x=1
def inner():
print(f"x={x}")
inner() #属于闭包函数
--------------------------------->>>>
def out(x):
def inner():
print(f"x={x}")
inner() #属于闭包函数,参数也属于局部变量
例子:求两个数字的和
常规写法
def sum(a,b)
return a+b
闭包写法
def funOut(num1):
def funIn(num2):
#内部函数修改外部函数的变量
nonlocal num1
num1+=100
return num2+num1
return funIn
f=funOut(100)
print(f) #打印的是funIn的地址 返回值是funIn
ret=f(200)
print(ret) #300
- 在不改变源代码的前提下,进行添加修改
- 例子:调用函数时添加一个日志功能
def writeLog(func):
print("访问了方法名:",func.__name__,"\t时间:",time.asctime())
def funcOut(func):
def funcIn():
writeLog(func) #在函数前加功能 后面也可以加功能
func()
return funcIn
def fun1():
print('jiajia')
fun1=funcOut(fun1)
fun1()
------------------------------>>
访问了方法名: fun1 时间: Sun Aug 25 13:59:00 2024
jiajia
就是一种闭包,使闭包的访问形式更方便
def w1(func):
def inner():
#验证1
#验证2
func()
return inner()
------------------------------------------------------------------->>>
调用w1函数,同时把f1传进去,返回inner函数-----调用inner(),验证之后,执行f1()
经过w1装饰的f1,指向了inner函数地址,效果等同于f1()=w1(f1)
------------------------------------------------------------------->>>
d
@w1
def f1():
print('f1')
例子:调用时添加日志信息
第一步:添加的新功能编写
#写一个输出日志功能
import time
def writeLog(func):
#添加一个异常判断
try:
file=open("log,txt",'b',encoding='utf-8')
file.write("访问:")
file.write(func.__name__) #获取函数的名字
file.write("\t")
file.write("时间:") #获取时间
file.write(time.asctime())
file.write("\t")
except Exception as e:
print(e.args)
finally:
file.clos() #释放资源
第二步:写一个闭包
def funcOut(func):
def funcIn():
writeLog(func) #内部函数引用外部函数
func()
return funcIn
第三步:装饰器调用
@funcOut #相当于fun1=funcOut(fun1)
def fun1():
print("功能1")
@funcOut
def fun2():
print("功能2")
例子:给foo函数新增2个功能,两个装饰器实现
第一步:编写新功能
print("i am foo")#比较简单可省略 直接写到闭包里
print("hello")#比较简单可省略 直接写到闭包里
第二步:写2个闭包
def funOut1(func):
def funIn():
print("i am foo") #调用函数前,加的新功能1
func()
return funIn
------------------------------------------------
def funOut2(func):
def funIn():
print("hello") #调用函数前,加的新功能2
func()
return funIn
第三步:装饰器调用
@funOut2 #hello 先调用
@funOut1 #i am foo 后调用
def foo():
print("这是foo的原本功能")
foo()
------------------------------------------>>
hello
i am foo
这是foo的原本功能
(1)、带同等数量的参数
注意:内部函数也要同步定义同等数量的参数 才能确保装饰器调用不出错
例子:打印函数的名称和时间
第一步:添加新功能
import time
def writeLog(func):
print("访问了方法名:",func.__name__,"\t时间:",time.asctime())
第二步:编写装饰器
def funOut(func):
def funIn(a,b):
writeLog(func)
return func(a,b)
return funIn
第三步:装饰器调用
@funOut
def sum(a,b):
return a+b
s=sum(10,15)
print(s)
解释
(2)、通用装饰器
- 注意:通用装饰器:*args,**kwargs
- 元组 字典 接收多个值 多个字典
例子:返回一个函数的名称和时间
import time
def funcOut(func):
def funcIn(*args,**kwargs):
writeLog(func)
return func(*args,**kwargs)
return funcIn
def writeLog(func):
print("访问了方法名:",func.__name__,"\t时间:",time.asctime())
@funcOut
def sum(a,b,c):
return a+b+c
s=sum(1,2,3)
print(s)
(3)、装饰器本身带有参数
注意:它就是一个函数 会被立即执行 返回结果是一个装饰器
第一步:新功能(省略)
第二步:装饰器
import time
import random
def loglever(level):
def w(func):
def inner(a, b):
start_time = time.time()
func(a, b)
end_time = time.time()
print(f"运行时间为{end_time - start_time}")
if level == "INFO":
print("it's info level")
return inner
return w #返回值w是装饰器
第三步:调用
@loglever("INFO")
def add_demo(a,b):
time.sleep(random.randrange(1, 5))
print(a+b)
解释:
问题:给一个函数添加一个功能,计算这个函数的运行时间为多少?
1.不使用装饰器实现
import time
import random
def time_demo():
start_time=time.time()
time.sleep(random.randrange(1,5))
print("welcome to xx")
end_time=time.time()
print(f"运行时间为{end_time-start_time}")
time_demo()
2.装饰器实现
第一步:编写新功能(省略)
第二步:编写装饰器
def funout(fun):
def inner():
start_time = time.time()
fun()
end_time = time.time()
print(f"运行时间为{end_time - start_time}")
return inner
第三步:装饰器调用
@funout
def time_demo():
time.sleep(random.randrange(1,5))
print("welcome to xx")
time_demo()
本文先介绍了函数的一些特性,详细的介绍了闭包、闭包的条件使用,以上两个主要为装饰器做铺垫,最后详细的介绍了装饰器的用法。如果理解起来有难度,多敲几遍,就能get到用法。