1、函数对象
在python中,函数是第一类对象、第一等公民
本质:函数可以当变量用,故引发下列操作:
1、可以被赋值
例:
def func():
print('from func')
f = func
print(f)
f()
2、可以当参数传给另外一个函数
def foo(x):
x()
foo(func)
3、可以当做函数的返回值
def foo(x):
return x
res = foo(func)
print(res)
4、可以当做容器类型的元素
l = [func,]
l[0]() #调用函数
加括号会触发一段代码的运行,变量不行
2、函数的嵌套 #在函数里在定义另一个函数
例:
def max2(x,y):
if x>y:
return x
else:
return y
def max4(a,b,c,d):
res1 = max2(a,b) #调用max2函数
res2 = max2(res1,c)
res3 = max2(res2,d)
return res3
定义:
def f1(x):
def f2():
print(x)
print(f2)
f1()
3、名称空间与作用域
namespace名称空间:存放名字地方
内置名称空间:
存放内置的名字
生命周期:python解释器启动则出现,关闭则销毁
全局名称空间:
存放顶级的名字(除了在函数里的名字,文件里的名字)
生命周期:运行python文件时产生,运行完毕则销毁
局部名称空间: 存放函数内的名字
生命周期:调用函数时产生,函数调用结束后销毁
名称空间并不存在嵌套关系,名字找寻顺序(名字访问优先级) 基于当前函数内->外层函数->全局->内置名称空间 (LEGB)
定义函数名不能产生名称空间,只有调用的时候才会产生名称空间
例:
len = 10
def func():
len = 20
print(len)
func()
print(len)
例2:
x = 111
def f1():
print(x)
def f2():
x=222
f1()
f2()
ps:此时x=111,不要看f2的局部名称空间
例3:
x=111
def f1():
print(x)
x=222
f1()
此时会报错,优先调用f1的x,但应该遵循先定义后调用的原则
由此可见名称空间与作用域的关系 是在函数定义阶段(扫描语法的时候)确定的,与调用位置无关(**)
作用域:
全局作用域:
内置名称空间 + 全局名称空间
特点:全局存活,全局有效
局部作用域:
局部名称空间
特点:临时存活,局部有效
global
x = 111
def func():
global x #声明变量名是来自于全局的
x = 222
func()
print(x) #当全局变量为不可变类型时,若不加global x 就无法改掉全局变量,同时要注意不要在局部作用域里更改全局作用域的变量,
否则多个函数一起更改时,无法确定全局变量
x = 111
def func():
nonlocal x #声明变量名是来自于外层函数的,不是全局,它永远不会去全局找,只会在外层函数打转
x = 222
func()
print(x)
4、闭包函数=函数对象+函数嵌套+名称空间与作用域
闭:指的是该函数是定义在函数内的函数
包:指的是该函数引用了一个外层函数作用域的名字 #闭包函数就是一种为函数体传参的方案
def outter(x):
def wrapper():
print(x)
return wrapper
f1 = outter(111)
f1()
#在这里想给wrapper传参,直接传就可以了
引升内容:
装饰器:
什么是装饰器?
装饰器就是一个用来为被装饰对象添加新功能的工具
2、为何要用装饰器
开放封闭原则:一旦软件上线运行之后,应该对修改源代码封闭,对扩展功能开放
原则:
1、不修改函数内的源代码
2、不修改函数的调用方式
装饰器就是在遵循原则1和原则2的前提下,为被装饰对象添加上新功能
下面就是装饰器的一个应用,用于检测程序运行时间的一个装饰器
import time
def timer(func):
def wrapper():
start=time.time()
res=func()
stop = time.time()
print("程序运行了%s秒"%(stop-start))
return res
return wrapper
index=timer(index)
index()