函数和变量有相通之处。变量的使用原则是先定义后引用,函数的使用原则是先定义后使用。变量名绑定了变量值对应的内存空间的内存地址。函数名绑定了函数体代码对应的内存空间的内存地址。因此,适用于变量名使用的场景也适用于函数名的使用场景。
变量
a=10
b=a
函数
def func():
print(1)
f=func
print(f)----->func的内存地址
f()----->1
变量
a=10
def func(x):
...
func(a)
函数
def index():
...
def func(m):
...
func(index)
变量
a=10
def func():
return a
函数
def index():
...
def func():
return index
res=func()
res()
变量
a=10
list1=[a]
list1[0]
函数
def func():
...
list1=[func]
list1[0]()
第四种函数对象的使用方法可以让我们之前写过的atm功能更加简洁:
def login():
...
def register():
...
def withdraw():
...
def deposit():
...
def transfer():
...
func_info={
'0':['退出',exit],
'1':['登录',login],
'2':['提现',register],
'3':['存钱',withdraw],
'4':['转帐',transfer]
}
while True:
for key,value in func_info:
print(key,value[0])
choice=input('请输入您想执行的操作: ').strip()
if choice in func_info():
print('您正在执行 {} 操作'.format(func_info[choice][0]))
func_info[choice][-1]()
def func():
x=10
def sub_func():
print(1)
func()----->None
def func():
x=10
def sub_func():
print(1)
sub_func()
func()----->1
比较输入的多个值的最大值的函数
def max2(x,y):
if x>y:
return x
else:
return y
def max_many(*args):
list1=list(args)
res1=list1[0]
if len(list1)>=2:
for i in range(1,len(list1)):
res1=max2(res1,list1[i])
print(res1)
名称空间namespaces
名称空间与作用域在定义阶段就确定了,而不是调用阶段
名称空间与作用域在定义阶段就确定了,而不是调用阶段
名称空间与作用域在定义阶段就确定了,而不是调用阶段
名称空间种类 | 定义 | 生命周期 |
---|---|---|
内置名称空间 | 存放内置的名字 | python解释器调用产生-python解释器关闭销毁 |
全局名称空间 | 存放的是顶级的名字 | python文件运行产生-python文件停止运行销毁 |
局部名称空间 | 存放的是函数内的名字 | 调用函数时产生,调用结束销毁 |
三种名称空间没有任何相交关系,但为了方便理解,可以理解为三层结构。内置名称空间在在外层,内层包含若干个(和python文件个数相同)全局名称空间,全局名称空间内层包含若干个(和python文件中调用函数的个数相同)函数的局部名称空间。
即LEGB层次。local----->enclosing functions----->global----->built-in functions.
案例一:
def f1():
x=555
def f2():
x=666
print(x)
f2()
x=444
f1()----->666
def f1():
x=555
def f2():
print(x)
f2()
x=444
f1()----->555
def f1():
def f2():
print(x)
f2()
x=444
f1()----->444
案例二:
len=10
def func():
len=2
print(len)
func()----->2
len=10
def func():
print(len)
func()----->10
def func():
print(len)
func()----->len的内置名称空间的内存地址
案例三:名称空间与作用域只与定义阶段有关,与调用无关
x=111
def f1():
print(x)
def f2():
x=222
f1()
f2()----->111
案例四:
x=111
def f1():
print(x) # local variable 'x' referenced before assignment
x=222
f1()
print(y) # name 'y' is not defined
x=10
def func():
global x
x=20
print('before func:',x)----->10
func()
print('after func:',x)----->20
x=10
def index():
x=20
def func():
nonlocal x
x=10
print('before func:',x)
func()
print('after func:',x)
index()----->20
----->10
闭:定义在函数内的函数
包:该函数引用了一个外层函数作用域的名字
def outter():
x=10
def wrapper():
print(x)
return wrapper
闭包函数其实就是另一种给函数传参的方式
为函数传参的两种方式:
def wrapper(x,y):
print(x+y)
wrapper(1,2)----->3
def outter(x,y):
def wrapper():
print(x+y)
return wrapper
f=outter(3,4)
f()----->7
装饰器就是为被装饰对象添加新功能的工具。
开放封闭原则:
开放:对扩展新功能开放
封闭:对修改原代码封闭
原则:
1.不修改原函数的原代码
2.不改变原函数的调用方法
无参装饰器模板
def outter(func):
def wrapper(*args,**kwargs):
res=func()
return res
return wrapper
有参装饰器模板
def chuancan(args):
def outter(func):
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
return outter
为了是使用装饰器的时候调用更加简便,引入了语法糖的概念。
import time
def outter(func):
def wrapper(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
end=time.time()
print(end-start)
return res
return wrapper
@outter
def index():
time.sleep(1)
print(123)
index()----->123 1.0028467
def deco1(func1): # func1=wrapper2
def wrapper1(*args,**kwargs):
print(111)
res1=func(*args,**kwargs)
print('end1')
return res1
return wrapper1
def deco2(func2): # func2=wrapper3
def wrapper2(*agrs,**kwargs):
print(222)
res2=func(*args,**kwargs)
print('end2')
return res2
return wrapper2
def deco3(func3): # func3=index
def wrapper3(*args,**kwargs):
print(333)
res3=func3(*args,**kwargs)
print('end3')
return res3
return wrapper3
@deco1 # deco1(wrapper2)--->return --->wrapper1
@deco2 # deco2(wrapper3)--->return--->wrapper2
@deco3 # deco3(index)--->return--->wrapper3
def index():
print('from index')
index()----->111
222
333
from index
end3
end2
end1
装饰器只需要看最内层的函数体代码就可以了,多个装饰器嵌套执行顺序从上到下
装饰器只需要看最内层的函数体代码就可以了,多个装饰器嵌套执行顺序从上到下
装饰器只需要看最内层的函数体代码就可以了,多个装饰器嵌套执行顺序从上到下