No.13装饰器&推导式
NO.13
今日概要
- 作业题
- 装饰器
- 推导式
- 模块
内容回顾
1.函数
-
参数
-
位置参数 > 关键字参数
-
默认参数:推荐使用不可变类型,慎用可变类型。
-
*args / **kwarge
- 接收任意个位置参数和关键字参数
- 位置参数一定放在关键字参数前面
-
函数可以作参数
def func(arg): arg() def show(): pass func(show) -
函数的参数传递的是什么?
v = [1,2,3,4] def func(arg): print(id(arg)) #列表的内存地址 print(id(v)) #列表的内存地址 func(v) #传递的是内存地址(引用)
-
-
返回值
-
常见数据类型可以返回
-
函数也可以返回
def func(): def inner(): pass return inner v = fun() -
特殊
- 默认返回值为None
- return 1,2,3 等价于 return (1,2,3)
-
-
执行函数
-
函数不被调用,内部代码永远不会执行。
def func(): return i func_list = [] for i in range(10): func_list.append(func) print(i) # 9 v1 = func_list[0]() # 9 v2 = func_list[5]() # 9func_list = [] for i in range(10): func_list.append(lambda :i) #函数不被调用,内部永远不执行。(不知道是什么。) # func_list.append(lambde :x) print(func_list) #无论有没有x,函数未执行程序都不会报错。 v = func_list[2]() #执行函数时没有x,此时才会报错。 -
函数执行时,才会开辟内存保存本次执行时的信息 → 闭包
def func(arg): def inner(): return arg return inner v1 = func(1) # 第一次执行时开辟内存1存储{ arg=1 , inner第一个地址} v2 = func(2) # 第二次执行时开辟内存2存储{ arg=2 , inner第二个地址} ret1 = v1() # 1 ret2 = v2() # 2def base(): return i def func(arg): def inner(): return arg return inner base_list = [] # 内部元素指向都是base函数地址 func_list = [] # 内部元素指向i=10个inner函数地址 for i in range(10): base_list.append(base) func_list.append(func(i)) #1.base_list 和 func_list 分别保存的是什么? 前者放的是base函数的地址,后者放的是inner函数的地址,且每个地址都不同。 #2.如果循环打印的是什么? for item in base_list: v = item() # 执行base函数 print(v) # 全是9 for data in func_list: v = data() print(v) # 0 1 2 ~ 9
-
总结:
- 传参:位置参数 > 关键字参数
- 函数不被调用,内部代码永远不执行。
- 每次调用函数时,都会为此次调用开辟一块内存。内存中可以保存自己以后想要用的数据。
- 函数是作用域,如果自己作用域中没有数据,则往上级作用域找数据。
2.内置和匿名函数
- 内置函数



- 匿名函数
3.模块
- getpass
- random
- hashib
使用模块时要先导入,本质就是导入一个py文件,然后调用此文件内的函数。
内置函数也是py文件,按理使用时也应该先导入,只不过解释器帮我们做了导入这个步骤。
python创始人会根据程序员的使用频率情况,把模块中的常用函数升级成内置函数(省去导入步骤),或把已有内置函数中很少用的函数降级放入模块。
内容详细
1.作业题讲解





2.装饰器
def func():
pass
v = func
#分割
def base():
print(1)
def bar():
print(2)
bar = base # bar本来指向其自身函数地址,被赋值后指向base函数地址。
bar() # 运行的是base,结果为1。
def func():
def inner():
pass
return inner
v = func() # inner函数
#分割
def func(arg):
def inner():
print(arg)
return inner
v1 = func(1)
v2 = func(2)
#分割
def func(arg):
def inner():
arg()
return inner
def f1():
print(123)
return 666
v1 = func(f1)
result = v1() # inner没有返回值
print(result) # None
#分割
def func(arg):
def inner():
return arg()
return inner
def f1():
print(123)
return 666
v1 = func(f1)
result = v1()
print(result)
引入装饰器
def func():
print(1)
v1 = func
func = 666 #可以认为函数名是个变量指向函数体的内存地址,现在这个变量被重新赋值为666了。
def func(arg):
def inner():
return arg()
return inner
def index():
print('123')
return '666'
示例一
v1 = index() # 执行index函数,打印123并返回666赋值给v1
示例二
v2 = fun(index) # v2是inner函数,arg = index 函数
index = 666
v3 = v2()
示例三
v4 = func(index)
index = v4 # index → inner地址
index()
#示例三的简写
index = func(index)
index()
#上述绕来绕去意义何在?
#在于不改变原函数内部代码的基础上,在其执行前后自定义一些代码进行操作。
def func(arg):
def inner():
print('before')
v = arg()
print('after')
return v
return inner
def index():
print('123')
return '666'
index = func(index)
index()
#简写版
def func(arg):
def inner():
print('before')
v = arg()
print('after')
return v
return inner
@func # 第一步:执行@的函数并将下面的函数当作参数传递。相当于:func(index)
def index(): # 第二步:将@的函数执行后的返回值重新赋值给下面的函数名。相当于:index = func(index)
print('123')
return '666'
index()
装饰器:在不改变原函数内部代码的基础上,在函数执行前后自动执行某些功能。
应用:想要为函数扩展功能时,可以选择用装饰器。
#计算函数执行时间
import time
def wapper(func):
def inner():
start = time.time()
v = func()
end = time.time()
print(end-start)
return v
return inner
@wapper
def func1():
time.sleep(2)
print(123)
@wapper
def func2():
time.sleep(2)
print(123)
@wapper
def func3():
time.sleep(2)
print(123)
func1()
func2()
func3()
#管理已登录的用户
def add_user():
#1.判断用户是否登陆
#2.已经登陆可以继续
pass
def del_user():
#1.判断用户是否登陆
#2.已经登陆可以继续
pass
def update_user():
#1.判断用户是否登陆
#2.已经登陆可以继续
pass
总结
-
目的:在不改变原函数的基础上,在函数执行前后自定义功能。
-
装饰器的编写和使用
#编写 def x(func): def y(): #前加功能 ret = func() #后加功能 return ret return y #使用 @x def index(): pass @x def manage(): pass #执行函数时,自动触发装饰器 v = index() print(v) -
记住
-
装饰器编写格式
def 外层函数(func): def 内层函数(*args,**kwargs): return func(*args,**kwargs) return 内层函数 -
装饰器使用格式
@外层函数 def index(): pass index() -
问题:为什么要加*args,**kwargs
def wrapper(func): def inner(*args,**kwargs): print('before') v = func(*args,**kwargs) print('after') return v return inner @wrapper def index(): print(123) index() @wrapper def show(a1): print(a1+100) show(1)
-
3.推导式
-
列表推导式
-
基本格式
#目的:方便的生成一个列表 变量 = [ 变量 for i in 可迭代对象] v = [ i for i in 可迭代对象 if 条件] 条件为True才添加#变量 = [ 变量 for循环的一个可迭代对象 ] v1 = [ i for i in 'alex' ] v2 = [ i+100 for i in range(10)] v3 = [ 100 for i in range(10)] v4 = [ 99 if i>5 else 66 for i in range(10)] def fun(): return 100 v5 = [ func for i in range(10)] v6 = [lambda :100 for i in range(10)] result = v6[0]() result = v6[9]() def fun(): return i v7 = [ func for i in range(10)] result = v7[0]() v8 = [lambda :i for i in range(10)] result = v8[0]()#面试题1 v = [lambda x:x*i for i in range(10)] #1.请问v是什么? #2.请问v[0](2)的结果是什么? #面试题2 def num(): return [lambda x:i*x for i in range(4)] # num() → [函数,函数,函数,函数] print([m(2) for m in num()]) # [6,6,6,6]#筛选 v9 = [ i for i in range(10) if i > 5] [6,7,8,9]
-
-
集合推导式
#不常用,除了括号和去重其余都和列表一样。 #注意:不是所有类型都能当集合元素。 v = { i for i in 'alex'} -
字典推导式
#不常用,除了括号和冒号其余都和列表一样。 #注意:不是所有类型都能当键值。 v = { 'k'+str(i):i for i in range(10)} v = { 'k':i for i in range(10)} # k重复最后结果{k:9}
总结
-
装饰器▲▲▲
-
编写格式:双层嵌套函数
-
使用格式:@外层函数
-
理解:
-
变量赋值
def func(): print(1) v = func func = 666 -
看清楚return到底是什么
-
自己作用域 → 上级作用域
-
-
背会
@x # index = xx(index) def index(): pass index()
-
-
推导式▲
-
模块
import time v = time.time() # 获取当前时间 time.sleep(2) # 执行到此会停两秒

浙公网安备 33010602011771号