回顾一下昨天有关引用传递与值传递有关的内容。
引用传递与值传递
可变对象为引用传递(传址),不可变对象为值传递(传值)。
传值和传址的区别 传值就是传入一个参数的值,传址就是传入一个参数的地址,也就是内存的地址(相当于指针)。他们的区别是如果函数里面对传入的参数重新赋值,函数外的全局变量是否相应改变,用传值传入的参数是不会改变的,用传址传入就会改变。
Python函数参数传递方式:传递对象引用(传值和传址的混合方式),如果是数字,字符串,元组(不可变对象)则传值;如果是列表,字典(可变对象)则传址;
举个例子:
a=1
def f(a):
a+=1
f(a)
print(a)
结果如下:
1
这段代码里面,因为a是数字类型,所以是传值的方式,a的值并不会变,输出为1
a=[1]
def f(a):
a[0]+=1
f(a)
print(a)
结果如下:
[2]
这段代码里面,因为a的类型是列表,所以是传址的形式,$a[0]$的值会改变,输出为$[2]$.
我们再打印一下a的地址:
def changelist(a):
a.append(0)
print(id(a))
print(a)
a = [4,5,6]
changelist(a)
print("-"*60)
print(id(a))
print(a)
返回结果为:
2375999356032
[4, 5, 6, 0]
------------------------------------------------------------
2375999356032
[4, 5, 6, 0]
发现在函数内部和函数外部,a的地址是一样的,说明a是传址的,而且在函数内部改变了a的值,函数外部的a的值也改变了。
函数作用域
所谓作用域(Scope),就是变量的有效范围,就是变量可以在哪个范围以内使用。有些变量可以在整段代码的任意位置使用,有些变量只能在函数内部使用,有些变量只能在 for 循环内部使用。
Python局部变量
在函数内部定义的变量,它的作用域也仅限于函数内部,出了函数就不能使用了,我们将这样的变量称为局部变量(Local Variable)。
要知道,当函数被执行时,Python 会为其分配一块临时的存储空间,所有在函数内部定义的变量,都会存储在这块空间中。而在函数执行完毕后,这块临时存储空间随即会被释放并回收,该空间中存储的变量自然也就无法再被使用。
举例子:
def demo():
add = "http://c.biancheng.net/python/"
print("函数内部 add =",add)
demo()
print("函数外部 add =",add)
运行结果如下:
函数内部 add = http://c.biancheng.net/python/
Traceback (most recent call last):
File "<ipython-input-3-3af67579cb4d>", line 5, in <module>
print("函数外部 add =",add)
NameError: name 'add' is not defined
可以看到,如果试图在函数外部访问其内部定义的变量,Python 解释器会报 NameError 错误,并提示我们没有定义要访问的变量,这也证实了当函数执行完毕后,其内部定义的变量会被销毁并回收。
Python全局变量
除了在函数内部定义变量,Python 还允许在所有函数的外部定义变量,这样的变量称为全局变量(Global Variable)。
和局部变量不同,全局变量的默认作用域是整个程序,即全局变量既可以在各个函数的外部使用,也可以在各函数内部使用。
定义全局变量的方式有以下 2 种:
- 在函数体外定义的变量,一定是全局变量,在函数内部也可以使用。
- 在函数体内定义全局变量。即使用 global 关键字对变量进行修饰后,该变量就会变为全局变量。
查看变量作用域
globals()函数
globals() 函数为 Python 的内置函数,它可以返回一个包含全局范围内所有变量的字典,该字典中的每个键值对,键为变量名,值为该变量的值。
举例子:
#全局变量
Pyname = "Python教程"
Pyadd = "http://c.biancheng.net/python/"
def text():
#局部变量
Shename = "shell教程"
Sheadd= "http://c.biancheng.net/shell/"
print(globals())
输出结果如下:
{ ...... , 'Pyname': 'Python教程', 'Pyadd': 'http://c.biancheng.net/python/', ......}
这个结果中,我们可以看到,全局变量 Pyname 和 Pyadd 的键值对都被包含在了 globals() 函数返回的字典中。
locals()函数
locals() 函数也是 Python 内置函数之一,通过调用该函数,我们可以得到一个包含当前作用域内所有变量的字典。这里所谓的“当前作用域”指的是,在函数内部调用 locals() 函数,会获得包含所有局部变量的字典;而在全局范文内调用 locals() 函数,其功能和 globals() 函数相同。
#全局变量
Pyname = "Python教程"
Pyadd = "http://c.biancheng.net/python/"
def text():
#局部变量
Shename = "shell教程"
Sheadd= "http://c.biancheng.net/shell/"
print("函数内部的 locals:")
print(locals())
text()
print("函数外部的 locals:")
print(locals())
程序执行结果为:
函数内部的 locals:
{'Sheadd': 'http://c.biancheng.net/shell/', 'Shename': 'shell教程'}
函数外部的 locals:
{...... , 'Pyname': 'Python教程', 'Pyadd': 'http://c.biancheng.net/python/', ...... }
当使用 locals() 函数获取所有全局变量时,和 globals() 函数一样,其返回的字典中会默认包含有很多变量,这些都是 Python 主程序内置的,读者暂时不用理会它们。
var(object)函数
vars() 函数也是 Python 内置函数,其功能是返回一个指定 object 对象范围内所有变量组成的字典。如果不传入object 参数,vars() 和 locals() 的作用完全相同。
Pyname = "Python教程"
Pyadd = "http://c.biancheng.net/python/"
class Demo:
name = "Python 教程"
add = "http://c.biancheng.net/python/"
print("有 object:")
print(vars(Demo))
print("无 object:")
print(vars())
程序执行结果为:
有 object:
{...... , 'name': 'Python 教程', 'add': 'http://c.biancheng.net/python/', ......}
无 object:
{...... , 'Pyname': 'Python教程', 'Pyadd': 'http://c.biancheng.net/python/', ...... }