今日大纲
1.昨日内容补充
2.函数名的应用
3.闭包
4.装饰器
1.昨日内容补充
def func1(*args,**kwargs): #聚合 11 22 33 变成(11, 22, 33)#聚合 变成{"name":"david"}
print(args) #11, 22, 33)
print(*args) #打散args 变成 11 22 33
print(kwargs) #打印{"name":"david"}
print(**kwargs) #报错,打散是name = "david",但是print函数不接受关键字参数
func1(*[11, 22, 33],**{"name":"david"}) #打散[11,22,33],变成 11 22 33 打散{"name":"david"} 变成 name="david"
典型例题:
def func():
def func1():
name ="老男孩"
def func2():
nonlocal name
name = "alex"
def func3():
global name
name = "太白"
name = "日天"
func1()
print(name) # 1 日天
func2()
print(name) # 2,alex
func3()
print(name) # 3,alex
func()
print(name) # 4,太白
2.函数名的应用
(1)直接打印函数名得到的是函数的内存地址
def func1():
print(func1) #<function func1 at 0x00000000021392F0>
func1()
(2)函数名可以赋值运算
def func1():
print(666)
f1 = func1
f1() #等同于 func1
(3)函数名可以作为函数的参数
def func1(x):
print(666)
x()
def func2():
print(333)
func1(func2)
(4)函数名可以作为容器型数据类型的元素
def func1():
print(111)
def func2():
print(222)
def func3():
print(333)
def func4():
print(444)
li = [func1,func2,func3,func4]
for i in li:
i()
dic = {1:func1,2:func2,3:func3,4:func4}
for k in dic:
dic[k]()
(5)函数名可以当做函数的返回值
def func1():
print(111)
def func2(x):
print(666)
return x
ret = func2(func1)
ret()
(6)第一类对象(first-class object)指
1)可在运行期创建
2)可用作函数参数或返回值
3)可存入变量的实体。
3.闭包
定义:内层函数对外层函数非全局变量的引用就是闭包。
如何判断是否是闭包:函数名.__closure__
返回值若为None则不是闭包;
返回值若为cell.....则是闭包
作用:当执行一个函数时,如果解释器判断此函数内部闭包存在,这样
Python就一个机制,闭包的所在的临时名称空间不会随着函数的执行完毕而消失。
def func1():
name = "david"
def func2():
print(name)
func2()
print(func2.__closure__)
func1()
执行结果:
david
(<cell at 0x000000000261D828: str object at 0x00000000025F2490>,)
def func1():
global name
name = "david"
def func2():
print(name)
func2()
print(func2.__closure__)
func1()
执行结果:
david
None
def func1(x):
#x = "老男孩"
def inner():
print(x)
inner()
print(inner.__closure__)
name = '老男孩'
func1(name)
执行结果:
老男孩
(<cell at 0x00000000021CD828: str object at 0x00000000021ACE70>,)
4.装饰器
def wrapper(f):
def inner(*args,**kwargs):
"""执行被装饰函数之前的操作"""
ret = f(*args,**kwargs)
"""执行被装饰函数之后的操作"""
return ret
return inner
装饰器功能:在不改变原函数的基础上,为原函数增加一些额外的功能,log,登录注册,等等.
题目:测试函数的效率
第一版本
import time
def func1():
time.sleep(0.3)
print("待到阴阳逆乱时,以我魔血染青天!")
def timmer():
start_time = time.time()
func1()
end_time = time.time()
print("用时%ss"%(end_time-start_time))
timmer()
第二版本
要求:要求可以测试多个函数
import time
def func1():
time.sleep(0.3)
print("待到阴阳逆乱时,以我魔血染青天!")
def func2():
time.sleep(0.4)
print("天地为棋,众生为子!")
def timmer(f):
start_time = time.time()
f()
end_time = time.time()
print("用时%ss"%(end_time-start_time))
timmer(func1)
timmer(func2)
第三版本
要求使用原函数执行方式
import time
def func1():
time.sleep(0.3)
print("待到阴阳逆乱时,以我魔血染青天!")
def timmer(f): #func1(f1) 时,执行函数
start_time = time.time()
f() #f1 就是要测试的函数的函数名func1
end_time = time.time()
print("用时%ss"%(end_time-start_time))
f1 = func1 #将func1 作为要传给timmer 形参f的 实参的位置参数,赋值给f1
func1 = timmer #定义一个新变量func1(不同于函数名func1),将函数名timmer 赋值给 func1
func1(f1) #我最终想要的func1(f1)等同于 timmer(func1)
第四版本
初级装饰器
import time
def func1():
time.sleep(0.3)
print("待到阴阳逆乱时,以我魔血染青天!")
def timmer(f): #f = func1
def inner():
start_time = time.time()
f() #f1 就是要测试的函数的函数名func1 # func1() 此时调用函数func1()
end_time = time.time()
print("用时%ss"%(end_time-start_time))
return inner
func1 = timmer(func1) # func1 = inner
func1() #inner()
第五版本
简单装饰器 语法糖
def timmer(f): #f = func1
def inner():
start_time = time.time()
f() #f1 就是要测试的函数的函数名func1 # func1() 此时调用函数func1()
end_time = time.time()
print("用时%ss"%(end_time-start_time))
return inner
@timmer #等同于 func1 = timmer(func1)
def func1():
time.sleep(0.3)
print("待到阴阳逆乱时,以我魔血染青天!")
func1() #inner()
@timmer # 等同于 func1 = timmer(func1)
def func2():
time.sleep(0.4)
print("天地为棋,众生为子!")
func2() #inner()
第六版本
能够传递参数的装饰器
import time
def timmer(f): #f = func1
def inner(*args,**kwargs): #(111,222)
start_time = time.time()
f(*args,**kwargs) #f 就是要测试的函数的函数名func1 # func1() 此时调用函数func1() #将(111,222)打碎 111 222
end_time = time.time()
print("用时%ss"%(end_time-start_time))
return inner
@timmer #等同于 func1 = timmer(func1)
def func1(a,b):
print(a,b)
time.sleep(0.3)
print("待到阴阳逆乱时,以我魔血染青天!")
func1(111,222) #inner(111,222)
@timmer # 等同于 func2 = timmer(func2)
def func2(a):
print(a)
time.sleep(0.4)
print("天地为棋,众生为子!")
func2(666) #inner(666)
第七版本
带返回值的装饰器
import time
def timmer(f): #f = func1
def inner(*args,**kwargs): #(111,222)
start_time = time.time()
ret = f(*args,**kwargs) #f 就是要测试的函数的函数名func1 # func1() 此时调用函数func1() #将(111,222)打碎 111 222
end_time = time.time()
print("用时%ss"%(end_time-start_time))
return ret
return inner
@timmer #等同于 func1 = timmer(func1)
def func1(a,b):
print(a,b)
time.sleep(0.3)
print("待到阴阳逆乱时,以我魔血染青天!")
return 666
print(func1(111,222)) #inner(111,222)
@timmer # 等同于 func2 = timmer(func2)
def func2(a):
print(a)
time.sleep(0.4)
print("天地为棋,众生为子!")
return 666
print(func2(777)) #inner(666)
例题:
from urllib.request import urlopen
def index():
url = "http://www.xiaohua100.cn/index.html"
def get():
return urlopen(url).read()
return get
xiaohua = index()
content = xiaohua()
print(content)