最近学习了闭包和装饰器,简单记录一下笔记,方便以后查阅。
- 关于闭包
- 1.什么是闭包
闭包就是一个函数
2.如何创建闭包
a.要有函数的嵌套(外部函数,内部函数)
b.内部函数要使用外部函数的变量
c.部函数必须有返回值,返回内部函数名
3.如何使用闭包 - 使用闭包,完成求两个数的和:
def fnout(x):
def fnin(y):
#内部函数要修改外部函数的变量用nonlocal
nonlocal x
x+=100
return x-y
return fnin
print(fnout(100)(400))
-200
- 使用闭包求两点之间的距离
import math
def fnout(x1,y1):
def fnin(x2,y2):
return math.sqrt((x1-x2)**2+(y1-y2)**2)
return fnin
print(fnout(1,1)(2,2))
1.4142135623730951
- 闭包的特殊用途:可以在不修改源代码的情况下,添加新的功能
添加日志输出功能
import time
def writelog(fn):
try:
file=open('writelog.txt','a',encoding='utf-8')
#向文件中写入日志信息(访问:方法名 时间:年月日)
file.write('访问:')
file.write(fn.__name__)
file.write('\t')
file.write('时间:')
file.write(time.asctime())
file.write('\n')
except Exception as e:
print(e.args)
finally:
file.close()
def fn1():
print('功能1')
- 使用闭包,不修改fn1,fn2的功能代码,添加日志信息
def fnout(fn):
def fnin():
writelog(fn)
fn()
print('使用了函数',fn.__name__)
return fnin
fnout(fn1)()
功能1
使用了函数 fn1
(writelog文档:
访问:fn1 时间:Tue Jun 8 16:24:35 2021)
- 装饰器的基本使用
在python程序中,装饰器就是一种闭包,他可以使闭包的访问方式更简单。
使用装饰器,完成不修改fn1,fn2函数的源码,添加输出日志信息
在python中使用装饰器,需要使用一个特殊的符号“@”来实现。在定义装饰器函数或类时,使用“@装饰器名称”的形式将符号“@”放在函数或类的定义行之前。
import time
def writelog(fn):
try:
file=open('writelog.txt','a',encoding='utf-8')
file.write('访问:')
file.write(fn.__name__)
file.write('\t')
file.write('时间:')
file.write(time.asctime())
file.write('\n')
except Exception as e:
print(e.args)
finally:
file.close()
def fnout(fn):
def fnin():
writelog(fn)
fn()
print('使用了函数',fn.__name__)
return fnin
@fnout
def fn1():
print('功能1')
fn1()
功能1
使用了函数 fn1
(writelog文档:
访问:fn1 时间:Tue Jun 8 16:31:05 2021)
- 多个装饰器的使用
给foo函数新增功能:在调用foo函数前面,输入“I am foo”
多个装饰器使用顺序:由近到远
def fnout(fn):
print('装饰器1')
def fnin():
print("I am foo")
fn()
return fnin
def fnout2(fn):
print('装饰器2')
def fnin():
print('hello')
fn()
return fnin
@fnout2
@fnout
def foo():
print('foo函数正在运行')
foo()
装饰器1
装饰器2
hello
I am foo
foo函数正在运行
- L带参数的装饰器与通用装饰器
(**args传入元组形式的参数,**kwargs 传入字典形式的参数) 或者写
def fnin(a,b),形参和传进来的函数形参一致)
import time
def writelog(fn):
print('访问了方法名:',fn.__name__,'\t',time.asctime())
def fnout(fn):
def fnin(*args):#(**kwargs 传入字典形式的参数) 或者写def fnin(a,b),形参数量和传进来的函数形参一致 ,
writelog(fn)
return fn(*args)
return fnin
@fnout
def sum(a,b):
return a+b
print('两数之和:',sum(10,20))
访问了方法名: sum Tue Jun 8 16:37:41 2021
两数之和: 30