009_作用域
1,作用域
- 全局作用域:作用域编写的整个程序;
- 局部作用域:作用域函数内部范围;
- 不同的局部作用域是独立的,不同域的函数可以使用相同的参数名。
- 局部作用域可以引用上级的局部作用域的变量,但是不可以修改。
- 在局部作用域,如果用了本域没有的变量就会向上级查找。
- 各自作用域的内的变量随着各自域的释放而释放,即函数内的变量随着函数的调用产生,随着函数的结束释放。
2,默认参数陷阱
- 如果默认参数的值是一个可变数据类型,那么每一次调用函数的时候,如果不赋值就公用这个数据类型的资源
def func(k = []):
k.append(1)
print(k)
func() #>>>[1]
func([]) #>>>[1]
func() #>>>[1,1]
func() #>>>[1,1,1]
3,函数名与内置函数名同名时
在正常情况下,直接使用内置函数的名字,调用内置函数但当我们在全局定义了和内置空间函数名相同时,会使用全局的名字
遵循原则,当自己有的时候就不在找上级要如果自己没有,就找上一级要,上级没有在再找上上级,如果内置空间都没有就报错
def input():
print('全局input')
input() >>>全局input
4,函数名地址
def input():
print('全局input')
def func():
print(input) #打印函数input()的地址
func() #>>><function input at 0x0000023EBD04D378>
- func指向一个地址,地址加()时一个函数的执行
- func————>函数的内存地址
- 函数名()————>函数的调用
- 函数的内存地址()————>函数的调用
5,函数调用全局变量
- 对于不可变数据类型 ,在局部可以查看全局作用域中的变量,但是不能直接修改
- 如果想要在局部作用域修改全局变量,需要在程序的一开始添加global声明
- 如果在一个局部(函数)作用域内声明了一个global变量,那么这个变量在局部的所有操作即是对全局变量的操作
a = 1
def func():
print(a) #局部可以查看全局变量
func() #>>>1
a = 1
def func2():
a += 1 #报错,局部不能更改全局变量
a = 1
def func3():
global a #声明变量a是全局变量a,修改即修改的全局变量a
a += 1
func3()
print(a) #>>>2
a=3
def func2():
a=0 #没有特殊声明,这是局部作用域func2函数范围的变量a
a += 1
print(a)
func2() #>>>1
print(a) #>>>3
6,查看局部变量,全局变量
- globals永远打印全局作用域的
- locals 意为:本地的,打印locals所在位置的作用域
a = 1
b = 2
def func():
x = '风'
y = '雨'
print(locals()) #查看局部变量 #>>>{'x': '风', 'y': '雨'}
func()
print(globals()) #查看全局变量 #输出的结果往后看
print(globals())
print(locals()) #此时打印的都一样,都是全局
7,函数的嵌套调用
#在一个函数里调用另一个函数
def thmax(x,y,z):
c = max(x,y)
return max(c,z)
print(thmax(2,3,4)) #>>>4
def outer():
def inner(): #局部作用域定义了一个函数
print('inner') #在局部空间内的内容,在调用时加载,结束之后就会释放(从内存空间删除)
inner()
outer() #>>>inner
#对于变量空间,被包含的属于下级,当自己需要东西时应向自己的上级索要
def outer():
a = 1
def inner():
print(a) #可以查看outer()作用域下的a,inner()在outer()空间中,outer()是innter()的上级。
print('inner')
inner()
outer() #>>>1 inner
8,global的讲解
- global代表的是声明的变量是全局的变量,不能被其他小局部同名变量改变
- 对于打印,下级局部可以查看上级变量,如本作用域没有就会向上级作用域查找
a = 1 #全局变量a
def outer():
a = 6 #outer()局部的变量a
def inner():
b = 2
print(a) #打印的是outer()局部作用域内的变量a
print('inner')
def inner2():
global a #声明在inner2()局部作用域内的变量a是全局变量
a += 1 #对全局变量a的操作
print('inner2')
inner2()
inner()
print(a) #outer()作用域中的a
outer()
print('全局a:',a)
结果: #注意:函数要先定义过才能执行,所以嵌套在一个函数内的新定义的函数
6 #需要包含新定义函数的这个函数执行的时候才会被定义
inner
inner2
6
全局a: 2
9,nonlocal 只能用于局部变量,对全局无效
- 对局部也只是对最后一层有影响
- 作用:声明本作用域中的这个变量是依次向上一级作用域找到的第一个同名的局部变量,在本作用域操作这个变量就是对依次向上一级作用域找到的第一个同名的局部变量的操作
10,函数名的讲解
#函数名可以赋值
def func():
print(123)
func2 = func #函数名可以赋值
func2() #>>>123
#函数名可以作为容器类型的元素
lis = [func,func2]
print(lis)
for i in lis:
i()
#函数名可以作为函数的参数
def wer(f):
f()
wer(func)
#函数名可以作为函数的返回值
def dnf(u):
u()
return u
re = dnf(func)
re()
11,闭包
11.1,嵌套函数,内部函数调用外部函数的变量
11.2,闭包的作用:平常的函数在调用时每次都要给变量开辟空间,释放变量。因此,对于需要频繁调用的函数来说浪费时间,降低了效率。
所以,在闭包中,在执行后,闭包外部函数的变量就会一只存在,直到程序的结束。通过将闭包内部函名返回出来,以便在全局作用域直接调用。
def outer():
a = 1
def inner():
print(a)
print(inner.__closure__) #查看是否是闭包,是闭包会显示cell
outer()
如上程序虽然是闭包,但不可以这样写,因为inner()就不会被调用。
11.3,闭包的简单使用
def outer():
a = 1
def inner():
print(a)
inner()
outer()
11.4,闭包的常用方式
def outer():
a =1
def inner():
print(a)
return inner
inn = outer()
inn()
12,闭包实例,网页代码的读取
12.1,网页代码的读取
from urllib.request import urlopen #导入模块中的一个方法
ret = urlopen('https://www.bilibili.com/').read() #网址要有效(能打开)
print(ret)
12.2,闭包的实例
from urllib.request import urlopen
def get_url():
url = 'https://www.bilibili.com/'
def get():
ret = urlopen(url).read()
print(ret)
return get
web = get_url()
web()