1.1名称空间的分类
名称空间的定义:存放名字与值的关系的空间起了一个名字
名称空间分为三种:
全局命名空间
局部命名空间
内置命名空间
A.全局名称空间
代码在运行伊始,创建的存储“变量名与值的关系”的空间
B.局部名称空间
在函数的运行中开辟的临时的空间
C.内置名称空间
存放了python解释器为我们提供的名input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。
1.2名称空间的一些规则
当程序运行时,代码从上至下一次执行,会将变量与值的关系存储在一个空间中,这个空间叫做名称空间,命名空间,全局名称空间。
当程序遇到函数时,他会将函数名存在内存中,函数体莫不关心。
当函数执行时,内存会临时开辟一个空间,存放函数体里面的代码(变量,代码等),函数外面访问不到临时空间的内容,随着函数的执行完毕,临时名称空间会释放掉,向这个临时开辟的空间叫临时名名称空间,也叫局部名称空间。
1.3作用域
作用域就是作用范围,按照生效范围可以分为全局作用域和局部作用域。
1.3.1全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
1.3.2局部作用域:局部名称空间,只能在局部范围内生效
1.4加载顺序
内置命名空间(程序运行前加载,也就是解释器运行的时候)->全局命名空间(程序运行中:从上到下加载)->局部命名空间(程序运行中:函数调用时才加载)
1.5取值范围
在局部调用:局部命名空间->全局命名空间->内置命名空间
在全局调用:全局命名空间->内置命名空间
综上所述,在找寻变量时,从小范围,一层一层到大范围去找寻。
2.1内置函数 globals() locals()
globals()返回字典,字典里面的内容是全局作用域
locals()返回字典,当前位置的所有变量
2.1.1全局范围运行globals() locals()
name='alex'
age=1000
def func1():
name1='oldboys'
age=10
# print(locals())
func1()
print(globals())
print(locals())
#此时打印的内容是一样的,其实都是全局的变量
# '__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001EBA3C8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/d22-01/day-4/练习.py', '__cached__': None, 'name': 'alex', 'age': 1000, 'func1': <function func1 at 0x0000000001E13E18>}
2.1.1局部范围运行locals()
name='alex'
age=1000
def func1():
name1='oldboys'
age=10
print(locals())
# {'age': 10, 'name1': 'oldboys'}
func1()
print(globals())
# '__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001EBA3C8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'E:/d22-01/day-4/练习.py', '__cached__': None, 'name': 'alex', 'age': 1000, 'func1': <function func1 at 0x0000000001E13E18>}
3.1关键字global and nonlocal
3.1.2
3.1.2.1 global:
1,声明一个全局变量。
2,在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字,布尔值)。
3,对可变数据类型(list,dict,set)可以直接引用不用通过global。
3.1.2.2 对于第2点的举例:
A.可引用并修改全局变量
count = 1
def func1():
global count
count=count+1
print(count)
func1()#count为2
B.在局部声明全局变量
def func1():
global name
name='alex'
func1()
print(name)#alex
3.1.2.3 对于第3点的举例:
l1=[1,2,3]
def func1():
l1.append(4)
print(l1)
func1()#[1, 2, 3, 4]
l1.append(5)
print(l1)# [1, 2, 3, 4, 5]
3.1.1
nonlocal: 1,不能修改全局变量。
2,在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。
def add_b():
b = 42
def do_global():
b = 10
print(b)#10
def dd_nonlocal():
nonlocal b
b = b + 20
print(b)#30
dd_nonlocal()
print(b)#30
do_global()
print(b)#42
add_b()
运行结果:
10
30
30
42
3.2取值的定义及规则
取值:引用而不是改变
取值是从小到大LEGB,想改变上层空间的变量,要用到global或者nonlocal
4.函数的嵌套和作用域
4.1函数的嵌套一:在一个函数调用全局定义的函数
def max2(x,y):
m = x if x>y else y
return m
def max4(a,b,c,d):
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
return res3
result=max4(23,-7,31,11)
print(result)#31
4.2函数的嵌套二:在函数里定义函数并调用函数
1.
def f1():
print("in f1")
def f2():
print("in f2")
f2()
f1()
#输出结果
in f1
in f2
2.
def f1():
def f2():
def f3():
print("in f3")
print("in f2")
f3()
print("in f1")
f2()
f1()
#输出的结果
in f1
in f2
in f3
4.3函数的作用域
小范围作用域可以使用大范围的变量,但是反之不行,他是单向的。
4.3.1例子1:
def f1():
a = 1
def f2():
def f3():
print(a)
f3()
f2()
f1()
#输出结果为1
例子2:
def f1():
a = 1
def f2():
a = 2
print('a in f2:',a)
f2()
print('a in f1:',a)
f1()
#输出结果:
a in f2: 2
a in f1: 1
5.函数名
5.1可被引用
def func():
print('in func')
f = func
print(f)# <function func at 0x00000000003B3E18>
5.2可作为容器元素
def func1():
print(111)
def func2():
print(222)
def func3():
print(333)
l1=[func1,func2,func3]
for i in l1:
i()
5.3函数名可作为参数传递
def func1():
print(111)
def func2(x):
x()
print(222)
func2(func1)
5.4函数名可以作为返回值
def func1():
print(111)
def func2():
print(222)
return func1
ret=func2()()
5.5函数名可作为变量赋值
def func1():
print(111)
return 111
f1=func1
f2=f1
f3=f2
f3()
print(f3)
5.6 第一类对象(first-class object)
1.可在运行期创建
2.可用作函数参数或返回值
3.可存入变量的实体。
6.闭包函数
内存函数对外层函数非全局变量的引用。
作用:用于装饰器和网络爬虫
6.1例子
def func():
name = 'eva'
def inner():
print(name)
return inner
f = func()
f()#输出eva
6.2判断闭包函数的方法__closure__
#输出的__closure__有cell元素 :是闭包函数
def func():
name = 'eva'
def inner():
print(name)
print(inner.__closure__)
return inner
f = func()
f()
#(<cell at 0x00000000027B65B8: str object at 0x00000000028382D0>,)
#eva
#输出的__closure__为None :不是闭包函数
name = 'egon'
def func2():
def inner():
print(name)
print(inner.__closure__)
return inner
f2 = func2()
f2()
#None
#egon
7.装饰器
装饰器本质上就是一个python函数,他可以让其他函数在不需要做任何代码变动的前提下,增加额外的功能,装饰器的返回值也是一个函数对象。
装饰器的应用场景:比如插入日志,性能测试,事务处理,缓存等等场景。
装饰器 本质就是闭包
7.1 装饰器的固定格式
def wrapper (func):
def inner(*args,**kwargs):
'''执行函数之前要做的'''
re = func(*args,**kwargs)
'''执行函数之后要做的'''
return re
return inner
7.2装饰器的应用
装饰器的应用在被装饰的函数前面
@wrapper
def essay():
print ('欢迎用户{}进入文章页面'.format (status_dict['username']))