一、名称空间namespacs

存放名字的地方,是对栈区的划分
有了名称空间之后,就可以在栈区中存放相同的名字,详细的,名称空间
分为三种

1.1 内置名称空间

存放的名字:存放的python解释器内置的名字
‘’’
>>> print

>>> input

‘’’
存活周期:python解释器启动则产生,python解释器关闭则销毁

1.2 全局名称空间

存放的名字:只要不是函数内定义、也不是内置的,剩下的都是全局名称空间的名字
存活周期:python文件执行则产生,python文件运行完毕后销毁

  1. import os
  2. x=10
  3. if 13 > 3:
  4. y=20
  5. if 3 == 3:
  6. z=30 # 都是顶级
  7. # func=函数的内存地址
  8. def func():
  9. a=111
  10. b=222 # 不是顶级的
  11. class Foo:
  12. 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、全局有效:被所有函数共享

  1. x=111
  2. def foo():
  3. print(x,id(x))
  4. def bar():
  5. print(x,id(x))
  6. foo()
  7. bar()
  8. 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:

  1. x=111
  2. def func():
  3. x=222
  4. func()
  5. print(x) # 111

示范2:如果再局部想要修改全局的名字对应的值(不可变类型),需要用global

  1. x=111
  2. def func():
  3. global x # 声明x这个名字是全局的名字,不要再造新的名字了
  4. x=222
  5. func()
  6. print(x) # 222

示范3:

  1. l=[111,222]
  2. def func():
  3. l.append(333)
  4. func()
  5. print(l)

nonlocal(了解): 修改函数外层函数包含的名字对应的值(不可变类型)

  1. x=0
  2. def f1():
  3. x=11
  4. def f2():
  5. nonlocal x
  6. x=22
  7. f2()
  8. print('f1内的x:',x)
  9. f1()
  10. print(x)

可变类型全局也会变

  1. x=[]
  2. def f1():
  3. x=[]
  4. def f2():
  5. x.append(1111)
  6. f2()
  7. print('f1内的x:',x)
  8. 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’

函数对象应用示范:

  1. def login():
  2. print('登录功能')
  3. def transfer():
  4. print('转账功能')
  5. def check_banlance():
  6. print('查询余额')
  7. def withdraw():
  8. print('提现')
  9. def register():
  10. print('注册')
  11. func_dic={
  12. '1':login,
  13. '2':transfer,
  14. '3':check_banlance,
  15. '4':withdraw,
  16. '5':register
  17. }
  18. # func_dic['1']()
  19. while True:
  20. print("""
  21. 0 退出
  22. 1 登录
  23. 2 转账
  24. 3 查询余额
  25. 4 提现
  26. 5 注册
  27. """)
  28. choice = input('请输入命令编号:').strip()
  29. if not choice.isdigit():
  30. print('必须输入编号,傻叉')
  31. continue
  32. if choice == '0':
  33. break
  34. if choice in func_dic:
  35. func_dic[choice]()
  36. else:
  37. print('输入的指令不存在')
  38. # if choice == '1':
  39. # login()
  40. # elif choice == '2':
  41. # transfer()
  42. # elif choice == '3':
  43. # check_banlance()
  44. # elif choice == '4':
  45. # withdraw()
  46. # else:
  47. # print('输入的指令不存在')

修正
def login():
print(‘登录功能’)

def transfer():
print(‘转账功能’)

三、函数嵌套

1、函数的嵌套调用

在调用一个函数的过程中又调用其他函数

  1. def max2(x,y):
  2. if x > y:
  3. return x
  4. else:
  5. return y
  6. def max4(a,b,c,d):
  7. # 第一步:比较a,b得到res1
  8. res1=max2(a,b)
  9. # 第二步:比较res1,c得到res2
  10. res2=max2(res1,c)
  11. # 第三步:比较res2,d得到res3
  12. res3=max2(res2,d)
  13. return res3
  14. res=max4(1,2,3,4)
  15. print(res)

2、函数的嵌套定义:

在函数内定义其他函数
def f1():
def f2():
pass

圆形

  1. from math import pi
  2. #求圆形的求周长:2*pi*radius
  3. def circle(radius,action=0):
  4. from math import pi
  5. def perimiter(radius):
  6. return 2*pi*radius
  7. # 求圆形的求面积:pi*(radius**2)
  8. def area(radius):
  9. return pi*(radius**2)
  10. if action == 0:
  11. return 2*pi*radius
  12. elif action == 1:
  13. return area(radius)
  14. circle(33,action=0)

四、闭包函数

1、大前提:

闭包函数=名称空间与作用域+函数嵌套+函数对象
核心点:名字的查找关系是以函数定义阶段为准

2、什么是闭包函数

“闭”函数指的该函数是内嵌函数
“包”函数指的该函数包含对外层函数作用域名字的引用(不是对全局作用域)

闭包函数:名称空间与作用域的应用+函数嵌套

  1. def f1():
  2. x = 33333333333333333333
  3. def f2():
  4. print(x)
  5. f2()
  6. x=11111
  7. def bar():
  8. x=444444
  9. f1()
  10. def foo():
  11. x=2222
  12. bar()
  13. foo()

闭包函数:函数对象

  1. def f1():
  2. x = 33333333333333333333
  3. def f2():
  4. print('函数f2:',x)
  5. return f2
  6. f=f1()
  7. # print(f)
  8. # x=4444
  9. # f()
  10. def foo():
  11. x=5555
  12. f()
  13. foo()

3、为何要有闭包函数=》闭包函数的应用

两种为函数体传参的方式
方式一:直接把函数体需要的参数定义成形参

  1. def f2(x):
  2. print(x)
  3. f2(1)
  4. f2(2)
  5. f2(3)

方式二:

  1. def f1(x): # x=3
  2. x=3
  3. def f2():
  4. print(x)
  5. return f2
  6. x=f1(3)
  7. print(x)
  8. x()

传参的方案一:

  1. import requests
  2. def get(url):
  3. response=requests.get(url)
  4. print(len(response.text))
  5. get('https://www.baidu.com')
  6. get('https://www.cnblogs.com/linhaifeng')
  7. get('https://zhuanlan.zhihu.com/p/109056932')

传参的方案二:

  1. import requests
  2. def outter(url):
  3. # url='https://www.baidu.com'
  4. def get():
  5. response=requests.get(url)
  6. print(len(response.text))
  7. return get
  8. baidu=outter('https://www.baidu.com')
  9. baidu()
  10. cnblogs=outter('https://www.cnblogs.com/linhaifeng')
  11. cnblogs()
  12. zhihu=outter('https://zhuanlan.zhihu.com/p/109056932')
  13. zhihu()