结论1、函数中,数值、字符、元组的传递是值传递
b = 5
print('id b = ',id(b))
def change(b):
print('\n')
#print('在函数change中 修改前 id b = ',id(b))
b = 0
print('在函数change中 修改后 id b = ',id(b))
def print_b():
print('\n')
print('在函数print b中 b =', b)
print('在函数print b中 id b = ',id(b))
def global_change():
global b
print('\n')
print('在函数global change中 修改前 id b = ',id(b))
b = 8
print('在函数global change中 修改后 id b = ',id(b))
change(b)
print_b()
global_change()
print_b()
print('\n\n\n\n','='*20,'')
结果如上所示:
1、在chage函数中 id 明显发生了改变,修改的不是同一个内存。
2、在global change 中由于增加了global关键字,所以开始时b变量指向的是同一块内存。而后修改变量,重新开辟空间,全局变量b指向新开的空间
3、在最后的printb中可以看出,全局变量b已经被修改。
# 元组类型
print(' *'*10,'元组'," *"*10)
d = ()
print('初始化后 id d : ',id(d))
def add_item_turple(d):
# 值传递
print()
print('函数中改变前 d: ',d)
print('函数中改变前 id d: ',id(d))
#global d
d+=(5,)
print('函数中改变后 d: ',d)
print('函数中改变后 id d: ',id(d))
print()
add_item_turple(d)
print('函数运行完后 d :',d)
print('函数运行完后 id d : ',id(d))
注:
b=8这句的执行过程并不是先获取x原来指向的对象的地址,再把内存中的值更改为8,而是新申请一段内存来存储对象8,再让x去指向对象8,所以两次id(x)的值不同。
’
结论2、函数中,数组、字典的传递是类似于引用的传递
a = [1,2,3,4,5,6]
print('原始 id a : ',id(a))
# 传参方式查看
def func_value_(a):
#global a
print('函数func_value_中 修改前id a : ',id(a))
a.append(666)
print('函数func_value_中 修改后id a : ',id(a))
def app_end():
#global a
print('函数append中 修改前id a : ',id(a))
a.append(666)
print('函数append中 修改后id a : ',id(a))
def print_a():
print(a)
print('函数printa中 id a : ',id(a))
print_a()
app_end()
print_a()
func_value_(a)
print_a()
print('\n\n\n\n','='*20,'')
可以看出,所有的id(a)均为同一值,说明在函数中和全局的数组修改是同一个数组。在python中数组作为参数的传递方式,是类似于引用传递,或地址传递的方式。这里不用加global语句,因为本来就是读取的全局变量。
c = {}
print(id(c))
def func_value_(dic):
print()
print('在func_value_ 函数中 修改前 id(c) 为:',id(dic))
dic['d'] = 88
print('在func_value_ 函数中 修改后 id(c) 为:',id(dic))
def add_item():
print()
print('在additem 函数中 修改前 id(c) 为:',id(c))
c['a'] = 99
print('在additem 函数中 修改后 id(c) 为:',id(c))
def print_c():
print()
print(c)
print('函数print c中 id c : ',id(c))
print_c()
add_item()
print_c()
func_value_(c)
print_c()
print('\n\n\n\n','='*20,'')
# set 类型
e = set()
print(id(e))
def add_item_set():
#global e
e.add(3)
print(id(e))
add_item_set()
print(e)
print(id(e))
# 其他数据类型 Lock 类型
import threading
lock = threading.Lock()
print(id(lock))
def lock_test():
print(id(lock))
lock.acquire()
print(id(lock))
lock_test()
结论
1、不可变数据类型 数字型、字符串型、元组 在使用时,如果不通过global关键字无法对全局变量进行修改(可以读取)。
2、可变类型、自定义类型 如 数组、set、字典类型 ,可以直接在函数中(不通过global关键字)即可修改全局变量。
3、如果通过传参方式,数字型、字符串型、元组 修改的是局部变量,需要通过返回值接收的方式修改全局变量。
4、可变类型如果通过传参方式传入函数中,也可直接修改全局变量。
5、在对数组、字典修改时,可以省略global关键字,数字型、字符串型、元组不可以。