1.locals和globals

1.1locals  获取当前作用域中的所有内容

locals 如果在函数外,调用locals(),获取打印的是打印之前的所有变量,返回字典,全局空间作用域
locals 如果在函数内,调用locals(),获取的是调用之前的所有变量,返回字典,局部空间作用域

#例子1

a = 1
b = 2
res = locals()
c = 3
print(res) #打印前面所有的变量的值,返回一个字典
d = 4 #不打印

a = 1
def outer():
def inner():
return 'www'
inner()
res = locals()
b = 2
c = 4
print(res) #打印前面所有全局变量,返回一个字典
d = 5 #不打印

#例子2
a = 1
def func():
b = 2 #这个是调用之前的局部变量
res =locals() #这个是调用
c = 3
print(res)#打印的是调用之前的局部内的变量是b = 2,返回字典形式{'b':2},
d = 4
func()


a = 1
def outer():
b = 2 #不会打印外函数的局部变量b=2
def inner():
c = 4 #内函数的局部变量
e = 6 #内函数的局部变量
res = locals() 调用
d =4
print(res) # 打印内函数的局部变量返回{'c':4,'e':6}
inner()
outer()

  

1.2globals 获取全局作用域的所有内容

globals 如果在函数外,调用globals(),获取打印的是打印之前的所有全局变量,返回字典,全局空间作用域
globals 如果在函数内,调用globals(),获取打印的是调用之前的所有全局变量,返回字典,全局空间作用域

#例子3
a = 5
b = 6
res = globals()
c = 7
print(res) #打印之前的所有变量 返回字典形式
d = 8 #不打印 该变量在打印之后

a = 1
def outer():
def inner():
return 'www'
inner()
res = globals()
b = 2
c = 4
print(res) #打印前面所有全局变量,返回一个字典
d = 5 #不打印

#例子4
a = 10 #全局变量
def func():
b = 11
c =12
res = globals() #调用
d = 13
print(res)#打印出的是调用之前的所有全局变量{'a':10,'ff':33}
ff = 33 #全局变量
func() #执行函数
zz = 50 #不打印,因为这是在整个func函数全部执行完才定义的全局全局变量

  

1.3globals返回的是系统的字典

#1.正常方式定义变量
zhangsan = '112233'


#2.通过系统的全局字典添加键值对,可以动态创建全局变量
dic =globals()
print(dic) ##{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001DEA2B0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/pythonproject/python_all/ceshi/day_01.py', '__cached__': None, 'dic': {...}}


# 传递字符串 ,创建一个变量
k = 'liuwei'
dic[k] = '刘伟' #键值对添加'liuwei':'刘伟'
print(liuwei) #通过键取值


#3.批量创建全局变量 在函数中
def func():
dic = globals()
for i in range(1,6):
dic['p%d'%(i)] = i #p1 p2 p3 p4 p5 p6
func()
print(p1) #1
print(p2) #2
print(p3) #3
print(p4) #4
print(p5) #5

  

2.函数的嵌套

函数的嵌套:
嵌套在函数的外边叫作外函数
嵌套在函数的里面叫作内函数
def outer():
def inner():
print('我是inner 函数')
inner()

outer()


#inner()
(1)内部函数可以直接在函数外部调用吗? 不可以
(2)调用外部函数后,内部函数可以在函数外部调用吗? 不可以
(3)内部函数可以在函数内部调用吗? 可以
(4)内部函数在函数内部调用时,是否由先手顺序? 有(必须先定义再调用)

#最外层outer,中间层inner,最里层smaller,调用smaller,执行里面的代码
def outer():
def inner():
def smaller():
print(id) #找的是内置的
print('我是smaller函数')
smaller()
inner()
outer()

# LEGB 原则(即就近找变量的原则)
#找寻变量的调用顺序采用LEGB原则(就近原则)
'''
B —— Builtin(Python) python内置模块的命名空间(内键作用域)
G —— Global(module) 函数外部所在的命名空间 (全局作用域)
E —— Enclosing function locals;外部嵌套函数的作用域 (嵌套作用域)
L —— Local(function); 当前函数内的作用域 (局部作用域)
依据就近原则,从下往上 从里向外,依次寻找
'''

  

3.nonlocal

nonlocal 关键字 用来更改局部变量
nonlocal 遵循LEGB原则
(1)nonlocal 专门用来修改当前作用域上一级的局部变量
(2)如果上一级找不到,那么就继续向上寻找
(3)全部找不到,直接报错 (不涉及全局变量)

#(1) nonlocal 专门用来修改当前作用域上一级的局部变量
def outer():
a = 10
def inner():
nonlocal a
a = 20
inner()
print(a) #a = 20
outer()

#(2) 如果上一级找不到,那么久继续向上寻找
'''nonlocal 只能修改局部变量'''
def outer():
a = 41
def inner():
def smaller():
nonlocal a
a = 42
print(a)
smaller()
print(a) #42
inner()
print(a) #42
outer()

#(3) 全部找不到,直接报错
a = 41
def outer():
def inner():
def smaller():
nonlocal a #找不到局部变量a 报错
print(a)
smaller()
print(a)
inner()
print(a)
outer()


#(4) 不使用nonlocal 是否可以修改局部变量呢?
def outer():
lst = [1,2,3]
def inner():
lst[-1] = 52
inner()
print(lst)
outer()

#当局部中有可变数据类型时,可以不使用nonlocal来修改全局变量
def outer():
dic = {'a'1,'b':2}
def inner():
dic['a'] = 5
inner()
print(dicvar)
outer()


#注意点 两者之间的区别
#第一种 这种是在函数内修改局部变量
def outer():
a = 10
def inner():
nonlocal a
a = 2
print(a) #a = 2
inner()
print(a) # a = 2
outer()
#第二种 这种是在函数内自己又定义了一个变量a,与外函数的局部变量不是同一个
def outer():
a = 10
def inner():
a = 2
print(a) # a = 2
inner()
print(a) # a = 10
outer()

  

4.闭包函数

闭包函数:
闭包函数:
内函数使用了外函数的局部变量
外函数将内函数返回出来的过程 叫作闭包
里面的内函数叫作闭包函数
#(1) 闭包函数用法
def wz_family():
father = '马云'
def mayun_hobby():
print('{0}不在乎钱'.format{father})
return mayun_hobby
# res = mayun_hobby <====> res() = mayun_hobby()
res = wz_family()
print(res) #打印出来的是一个函数内存地址
res() #加括号相当于调用函数
解析:
wz_family调用函数拿一个变量res接收,返回mayun_hobby,res = mayun_hobby,
内部函数mayun_hobby需要mayun_hobby加()执行,就可以用res()执行内部函数

#(2) 升级
def liuwei_familt():
father = '刘德华'
jiejie = '刘亦菲'
meimei = '杨颖'
money = 1000

def jiejie_hobby():
nonlocal money
money -= 600
print('穷的没钱了,还剩%s元'%(money))

def meimei_hobby():
nonlocal money
money -=200
print('我比你还穷,只剩下%s元'%(money))

def big_master():
return [jiejie_hobby,meimei_hobby]

return big_master

func = liuwei_familt() #返回的big_master
print(func)
res = func() #相当于调用了big_master()
print(res) #返回回来的是[jiejie_hobby,meimei_hobby]

#分别获取姐姐,妹妹这两个函数
jiejie = res[0]
jiejie() #相当于调用jiejie_hobby函数
meimei =res[1]
meimei()#相当于调用meimei_hobby函数


# ### 获取闭包函数使用的变量 __closure__,cell_contents(了解)
tup = func.__closure__
print(tup)
#(<cell at 0x0000000001E15618: function object at 0x0000000001E99AE8>,
# <cell at 0x0000000001E15678: function object at 0x0000000001E99B70>)

#cell_contents #功能获取单元对象里面的内容
jiejie = tup[0].cell_contents
meimei = tup[1].cell_contents
print(jiejie)
#<function weifuqiang_family.<locals>.jiejie_hobby at 0x0000000001E99AE8>
jiejie()
meimei()

  

5.闭包特点

闭包特点:
内函数使用了外函数的局部变量,该局部变量与内函数发生绑定,延长该变量的生命周期
#函数的定义处
def outer(var): #var = 5
def inner(num):
return num+var #num = 4
return inner

# 函数的调用处
func = outer(5)
res = func(4) # ==> inner()
print(res)
解析:
1.实参5 和形参var一一对应 进行接收val = 5
因为内函数inner 和 val进行绑定,延长了val变量的生命周期,不释放
func = outer(5) <====> func = inner
2,实参4 和形参num一一对应 进行接收num= 4
return num + val <===> 4+5 = 9

闭包的意义
闭包可以优先使用外函数的局部变量
局部变量在函数外部不能被直接使用
对局部变量实现了保护的作用,外部无法访问

#模拟鼠标点击操作

#方法一
click_num = 0
def click_func():
global click_num
click_num +=1
print(click_num)

click_func() #1
click_func() #2
click_func() #3
click_num = 100 #在函数内部声明click_num为全局变量并修改,所以在函数外部也可以修改这个全局变量
click_func() #101

#方法二
def outer():
click_num = 0
def inner():
nonlocal click_num #定义click_num是一个局部变量,在函数局部内有这个变量
click_num +=1
print(click_num)
return inner
#click_func = inner
click_func = outer()
click_func() #1
click_func() #2
click_func() #3
click_num = 100 #在函数外部不能修改局部内变量
click_func() #4
解析:
闭包函数:
首先外函数的局部变量click_num为0,内函数想修改外函数的局部变量就需要用nonlocal声明
然后才能修改
click_num = 100在函数外部不能修改函数内部的局部变量

  

6.匿名函数

匿名函数 lambda 表达式
用一句话来表达只有返回值的函数 特点:简洁,高效,方便
语法结构:
lanbda 参数:返回值

#(1) 无参的lambda表达式
def func():
return '我是大哥'

#改成lambda表达式
func = lambda : '我是大哥'
res = func()
print(res)

#(2) 有残的lambda 表达式
def func(n):
return type(n)

#用lambda表达式
func = lambda n : type(n)
res =func()
print(res)

#(3) 带有判断条件的lambda表达式
def func(n):
if n%2 == 0:
return '偶数'
else:
return '奇数'

三元(三目)运算符
真值 if 条件表达式 else 假值
如果条件表达式成立 为真 返回真值
如果条件表达式不成立 为假 返回假值

n = 20
res '偶数' if n%2 == 0 else '奇数'
print(res)

#lambda表达式
func = lambda n : '偶数' if n %2==0 else '奇数'
res = func()
print(res)

#练习
def func(x,y):
if x>y:
return x
else:
return y

func = lambda x,y : x if x>y else y
res = func(22,5)
print(res)

  

总结:今天主要讲了以下个点,locals和globals的用法,函数的嵌套,nonlocal,闭包函数及其特点以及匿名函数

locals:获取当前作用域中的所有内容

locals 如果在函数外,调用locals(),获取的是打印之前的所有变量,返回字典,全局空间作用域

locals 如果在函数内,调用locals(),获取的是调用之前的所有变量,返回字典,局部空间作用域

globals  获取全局作用域的所有内容

globals 如果在函数外,调用globals(),获取的是打印之前的所有全局变量,返回字典,全局空间作用域

globals 如果在函数内,调用globals(),获取的是调用之前的所有全局变量,返回字典,全局空间作用域

用globals可以通过系统的全局字典添加键值对,可以动态创建全局变量,也可以批量创建全局变量

函数的嵌套:

嵌套在函数的外边叫作外函数

嵌套在函数的里面叫作内函数

内部函数不可以直接在函数外部调用

调用外部函数后,内部函数不可以在函数外部调用

内部函数可以在函数内部调用

内部函数在函数内部调用时,有先后顺序(必须先定义再调用)

还讲了LEGB原则就是就近变量的原则,从下往上,从里向外

nonlocal 通用遵循LEGB原则:

专门用来修改当前作用域上一级的局部变量

如果上一级找不到,那么就继续向上寻找

全部找不到,直接报错 (不涉及全局变量)

不使用nonlocal可以修改局部变量,当外函数的局部变量是可变数据类型时,内函数可以不用nonlocal来修改局部变量

闭包函数:

内函数使用了外函数的局部变量

外函数将内函数返回出来的过程 叫作闭包

里面的内函数叫作闭包函数

还讲了两个获取闭包函数的函数,__closure__,cell_contents

闭包的特点:

内函数使用了外函数的局部变量 该局部变量与内函数发生绑定 延长该变量的生命周期

闭包可以优先使用外函数的局部变量
局部变量在函数外部不能被直接使用
对局部变量实现了保护的作用,外部无法访问

匿名函数:用一句话来表达只有返回值的函数  特点:简洁,高效,方便

语法结构:
lanbda 参数:返回值

三元运算符:

真值 if 条件表达式 else 假值
如果条件表达式成立 为真 返回真值
如果条件表达式不成立 为假 返回假值

 


-------------------------------------------

个性签名:代码过万,键盘敲烂!!!

如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!