一、名称空间namespacs
存放名字的地方,是对栈区的划分
有了名称空间之后,就可以在栈区中存放相同的名字,详细的,名称空间
分为三种
1.1 内置名称空间
存放的名字:存放的python解释器内置的名字
‘’’
>>> print
>>> input
‘’’
存活周期:python解释器启动则产生,python解释器关闭则销毁
1.2 全局名称空间
存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称空间的名字
存活周期:python文件执行则产生,python文件运行完毕后销毁
import osx=10if 13 > 3:y=20if 3 == 3:z=30 # 都是顶级# func=函数的内存地址def func():a=111b=222 # 不是顶级的class Foo:pass
1.3 局部名称空间
存放的名字:在调用函数时,运行函数体代码过程中产生的函数内的名字
存活周期:在调用函数时存活,函数调用完毕后则销毁
def func(a,b):
pass
func(10,1)
func(11,12)
func(13,14)
func(15,16)
1.4 名称空间的加载顺序
内置名称空间>全局名称空间>局部名称空间
1.5 销毁顺序
局部名称空间>全局名空间>内置名称空间
1.6 名字的查找优先级
当前所在的位置向上一层一层查找
内置名称空间
全局名称空间
局部名称空间
如果当前在局部名称空间:
局部名称空间—>全局名称空间->内置名称空间
# input=333
def func():
# # input=444
# print(input)
#
# func()
如果当前在全局名称空间
全局名称空间->内置名称空间
# input=333
# def func():
# input=444
# func()
# print(input)
示范1:
# def func():
# print(x)
# x=111
#
# func()
示范2:名称空间的”嵌套”关系是以函数定义阶段为准,与调用位置无关
# x=1
# def func():
# print(x)
#
#
# def foo():
# x=222
# func()
#
# foo()
示范3:函数嵌套定义(从内层找)
# input=111
# def f1():
# def f2():
# # input=333
# print(input)
# input=222
#
# f2()
#
#
# f1()
示范4:
# x=111
# def func():
# print(x) #
# x=222
#
# func()
二、作用域-》作用范围
全局作用域:
内置名称空间、全局名称空间
1、全局存活
2、全局有效:被所有函数共享
x=111def foo():print(x,id(x))def bar():print(x,id(x))foo()bar()print(x,id(x))
局部作用域:
局部名称空间的名字
1、临时存活
2、局部有效:函数内有效
def foo(x):
# def f1():
# def f2():
# print(x)
LEGB
# # builtin
# # global
# def f1():
# # enclosing
# def f2():
# # enclosing
# def f3():
# # local
# pass
global与nonlocal
示范1:
x=111def func():x=222func()print(x) # 111
示范2:如果再局部想要修改全局的名字对应的值(不可变类型),需要用global
x=111def func():global x # 声明x这个名字是全局的名字,不要再造新的名字了x=222func()print(x) # 222
示范3:
l=[111,222]def func():l.append(333)func()print(l)
nonlocal(了解): 修改函数外层函数包含的名字对应的值(不可变类型)
x=0def f1():x=11def f2():nonlocal xx=22f2()print('f1内的x:',x)f1()print(x)
可变类型全局也会变
x=[]def f1():x=[]def f2():x.append(1111)f2()print('f1内的x:',x)f1()
三、函数对象
精髓:可以把函数当成变量去用
func=内存地址
def func():
print(‘from func’)
1、可以赋值
f=func
print(f,func)
f()
2、可以当做函数当做参数传给另外一个函数
def foo(x): # x = func的内存地址
# print(x)
x()
foo(func) # foo(func的内存地址)
3、可以当做函数当做另外一个函数的返回值
def foo(x): # x=func的内存地址
return x # return func的内存地址
res=foo(func) # foo(func的内存地址)
print(res) # res=func的内存地址
res()
4、可以当做容器类型的一个元素
l=[func,]
# # print(l)
# l0
dic={‘k1’:func}
print(dic)
dic‘k1’
函数对象应用示范:
def login():print('登录功能')def transfer():print('转账功能')def check_banlance():print('查询余额')def withdraw():print('提现')def register():print('注册')func_dic={'1':login,'2':transfer,'3':check_banlance,'4':withdraw,'5':register}# func_dic['1']()while True:print("""0 退出1 登录2 转账3 查询余额4 提现5 注册""")choice = input('请输入命令编号:').strip()if not choice.isdigit():print('必须输入编号,傻叉')continueif choice == '0':breakif choice in func_dic:func_dic[choice]()else:print('输入的指令不存在')# if choice == '1':# login()# elif choice == '2':# transfer()# elif choice == '3':# check_banlance()# elif choice == '4':# withdraw()# else:# print('输入的指令不存在')
修正
def login():
print(‘登录功能’)
def transfer():
print(‘转账功能’)
三、函数嵌套
1、函数的嵌套调用
在调用一个函数的过程中又调用其他函数
def max2(x,y):if x > y:return xelse:return ydef max4(a,b,c,d):# 第一步:比较a,b得到res1res1=max2(a,b)# 第二步:比较res1,c得到res2res2=max2(res1,c)# 第三步:比较res2,d得到res3res3=max2(res2,d)return res3res=max4(1,2,3,4)print(res)
2、函数的嵌套定义:
在函数内定义其他函数
def f1():
def f2():
pass
圆形
from math import pi#求圆形的求周长:2*pi*radiusdef circle(radius,action=0):from math import pidef perimiter(radius):return 2*pi*radius# 求圆形的求面积:pi*(radius**2)def area(radius):return pi*(radius**2)if action == 0:return 2*pi*radiuselif action == 1:return area(radius)circle(33,action=0)
四、闭包函数
1、大前提:
闭包函数=名称空间与作用域+函数嵌套+函数对象
核心点:名字的查找关系是以函数定义阶段为准
2、什么是闭包函数
“闭”函数指的该函数是内嵌函数
“包”函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)
闭包函数:名称空间与作用域的应用+函数嵌套
def f1():x = 33333333333333333333def f2():print(x)f2()x=11111def bar():x=444444f1()def foo():x=2222bar()foo()
闭包函数:函数对象
def f1():x = 33333333333333333333def f2():print('函数f2:',x)return f2f=f1()# print(f)# x=4444# f()def foo():x=5555f()foo()
3、为何要有闭包函数=》闭包函数的应用
两种为函数体传参的方式
方式一:直接把函数体需要的参数定义成形参
def f2(x):print(x)f2(1)f2(2)f2(3)
方式二:
def f1(x): # x=3x=3def f2():print(x)return f2x=f1(3)print(x)x()
传参的方案一:
import requestsdef get(url):response=requests.get(url)print(len(response.text))get('https://www.baidu.com')get('https://www.cnblogs.com/linhaifeng')get('https://zhuanlan.zhihu.com/p/109056932')
传参的方案二:
import requestsdef outter(url):# url='https://www.baidu.com'def get():response=requests.get(url)print(len(response.text))return getbaidu=outter('https://www.baidu.com')baidu()cnblogs=outter('https://www.cnblogs.com/linhaifeng')cnblogs()zhihu=outter('https://zhuanlan.zhihu.com/p/109056932')zhihu()
