1、作用于的概念
变量作用域指的是变量生效的范围, 在中一共有两种作用域。
函数作用域的第二部分我们来讨论一下局部变量。
所谓局部变量呢, 它就是被定义在函数体内部的那些变量, 也就是只在函数体内部有效。
def testA():# 局部变量a
# 在函数中为变量赋值时,默认都是为局部变量赋值
# 局部变量不会影响函数外的变量。
a = 100
# 函数体内部访问,能访问到a变量
print(a)
testA() # 100
print(a) # 报错:name 'a' is not defined
变量a是被定义在了testA这个函数内部的变量, 如果我们想要在这个函数的外面去访问它的话, 那么程序就会立即报错。
局部变量的作用主要是在函数体的内部对数据进行临时的保存, 也就是说, 在函数调用完成之后, 就会把定义的局部变量进行销毁。
3、全局变量
所谓的全局变量, 实际上就是那种可以在函数体的内部起作用, 同时也可以在函数体的外部起作用的变量。
咱们来思考一下, 如果有某个数据项存在这种情况, 就是这个数据既需要在函数A里面被调用去使用的, 同时这个数据也得在函数B里面被使用到的。那么在这种情况下, 究竟应该怎么办?
回答这个问题的方法是, 把这个数据存储在一个被设置为全局状态的地方。
# 定义全局变量aa = 100
def testA():
print(a) # 访问全局变量a,并打印变量a存储的数据
def testB():
print(a) # 访问全局变量a,并打印变量a存储的数据
testA() # 100
testB() # 100
我们来思考一下, 如果想要通过修改程序来满足testB函数的需求, 也就是把变量a的值改成200, 我们应该怎么去动这个代码。
a = 100def testA():
print(a)
def testB():
a = 200
print(a)
testA() # 100
testB() # 200
print(f'全局变量a = {a}') # 全局变量a = 100
我们需要思考的一个问题是, 在testB这个函数的内部,表达式a等于二百的这个地方, 变量a到底是不是在对全局变量a进行修改操作呢。
回答是否定。通过对上述代码进行观察可以发现, 第15行获取到的变量a的数据是100, 这依然是定义全局变量a时候所对应的初始值, 该位置并没有执行返回操作。
在testB函数内部的那个数是200, 综合起来看, testB函数内部的a = 200这个操作其实是定义了一个局部变量。
(1)关键字
我们需要认真思考一下, 具体应当怎样在函数这个代码块的内部, 对全局变量进行修改操作。
a = 100def testA():
print(a)
def testB():
# 想要修改全局变量a的值是200
# global 关键字声明a是全局变量
global a
a = 200
print(a)
testA() # 100
testB() # 200
print(f'全局变量a = {a}') # 全局变量a = 200
关键字的作用体现在它能够对函数内部的变量施加一种声明, 使得这个变量能够转变为全局变量的身份。换用一种更加直白的表述方法来说, 倘若你期望在函数的内部完成对某个全局变量数值的修改操作, 这时候就必须借助于这个关键字来正式地声明相关的变量才行。
(2)总结
4、变量的查找
如果我们去拿那个变量来用, 咱们会先在当前的这个范围里头去找它, 要是找着了的话, 那就直接用。
如果没有找到, 就需要继续前往上一级的作用域里面去寻找那个目标, 直到发现它的存在并且最终使用它。
如果依然还是没有的话, 那就得继续去上一级的作用域里面去寻找了, 就这么一步一步地往后推下去。
一直到找到了全局作用域这个层级, 可是还是没有找到的时候, 就会抛出那个异常, 它的信息是名称为a的这个东西是不存在的。
# 练习说明a = 10
def fn2():
def fn3():
a = 30
print('fn3中:','a =',a)
fn3()
print('fn2中:','a =',a)
fn2()
"""
输出结果:
fn3中: a = 30
fn2中: a = 10
"""
5、在这个作用域里面, 那个类型是可变数据类型的变量。
c = 10def fn4(a):
# 在函数中对形参进行重新赋值,不会影响其他的变量
a = 20
print('a =', a, id(a))
fn4(c)
print('c =', c, id(c))
"""
输出结果:
a = 20 8791349231264
c = 10 8791349230944
"""
# 如果形参接收到的数据是一个全局列表
# 当在函数内尝试修改列表中的元素时,全局列表的数据也会发生改变
c = [1,2,3]
def fn4(a):
# 如果形参执行的是一个对象,当我们通过形参去修改对象时
# 会影响到所有指向该对象的变量
a[0] = 100
print('a =', a, id(a))
fn4(c)
print('c =', c, id(c))
"""
输出结果:
a = [100, 2, 3] 5132808
c = [100, 2, 3] 5132808
"""
# 如果我们不向全局变量有所改动
# 就需要使用我们之前学过的浅复制,
# 或者传入一个切片,就可以解决
c = [1, 2, 3]
def fn4(a):
# 在函数中对形参进行重新赋值,不会影响其他的变量
a[0] = 100
print('a =', a, id(a))
fn4(c.copy())
# fn4(c[:])
print('c =', c, id(c))
"""
输出结果:
a = [100, 2, 3] 6050824
c = [1, 2, 3] 6050312
"""
6、多函数程序执行流程
一般在实际的开发生活当中, 有一个程序通常是由许多个函数构成的, 而且这些众多的函数会一起去共享存在的数据, 这样的情况在下述内容里可以看到。
(1)大家可以一起来用那个全局范围内的公共变量。
# 1. 定义全局变量glo_num = 0
def test1():
global glo_num
# 修改全局变量
glo_num = 100
def test2():
# 调用test1函数中修改后的全局变量
print(glo_num)
# 2. 调用test1函数,执行函数内部代码:声明和修改全局变量
test1()
# 3. 调用test2函数,执行函数内部代码:打印
test2() # 100
(2)将返回值作为参数进行传递。
# 先得到函数一的返回值,再把这个返回值传入到函数二def test1():
return 50
def test2(num):
print(num)
# 1. 保存函数test1的返回值
result = test1()
# 2.将函数返回值所在变量作为参数传递到test2函数
test2(result) # 50