python中可变与不可变类型变量中一些较难理解的地方

  •  当函数内部引用一个全局变量时,若是此全局变量为可变类型,那么函数内部是能够改变此全局变量的值,用不用globale申明全局变量都同样。可是若是想给此变量从新赋值则必需要使用global。
l = []
d = {} def add_value(): d['frank'] = 'yangcaho' l.append(d) add_value() print(l) print(d) 输出: [{'frank': 'yangcaho'}] {'frank': 'yangcaho'}
l = []
d = {} def add_value(): global l global d d['frank'] = 'yangcaho' l.append(d) add_value() print(l) print(d) 输出: [{'frank': 'yangcaho'}] {'frank': 'yangcaho'}

 

  •   当函数内部引用一个全局变量时,若是此全局变量为不可变类型,那么若是要可以在函数内部改变全局变量的值,就须要用global,不用改变则不须要用global也能够引用
a = 'frank'
def add_value():
    global a a = 'yangchao' add_value() print(a) yangchao

 

a = 'frank'
def add_value():
    b = a + 'yangchao'
    print(b) add_value() print(a) frankyangchao frank

   结论:可使用定义在函数外的全局变量的值(假设在函数内没有同名的变量)。但强烈建议尽可能避免这样作,由于这使得程序的读者会不清楚这个变量是在哪里定义的。使用global语句能够清楚地代表变量是在外面的块定义的。app

一些细微区别

可变对象如list的.paaend()操做与‘+’操做,的一些不一样点。函数

  • 用 ‘+’ 其实是从新定义一个变量了。可是原列表的内存位置不会变,会开辟一个新的内存,L不是直接在原来l的基础上增长而后指向l
l = ['frank', 'liuilu']
print(id(l))
L  = l + ['yangchao']
print(id(L))
print(l)
print(id(l))

36364616
36365960
['frank', 'liuilu']
36364616

 

  • 用 append 和 ’ += ‘其实是在原来变量基础上增长。
l = ['frank', 'liuilu']
print(id(l))
l += ['yangchao']
print(l)
print(id(l))

43639112
['frank', 'liuilu', 'yangchao']
43639112
  •  一下代码中个很坑的地方:为何l的值不是[{'age': 1}, {'age': 2}]而是[{'age': 2}, {'age': 2}],由于l中存入的值是d实际是存入了d所指向内存地址。在第二次改变d的值得时候,就是改变了d的指向。因而第一次添加的d的值也会改变。
l = []
d = {} def add_value(): for i in range(1, 3): print('第%s次循环' %i) d['age'] = i print(d) print('#' * 10) print(l) print('#' * 10) l.append(d) print(l) add_value()  输出结果 第1次循环 {'age': 1} ########## [] ########## [{'age': 1}] 第2次循环 {'age': 2} ########## [{'age': 2}] ########## [{'age': 2}, {'age': 2}]

   可是函数内若是是用赋值的方式(以下面两种模式),那么函数中的d就再也不是全局变量中的d了。因此有了每次赋值操做(即’=‘),每次append的d都是新的值。不会改变原来的值。ui

l = []
d = {} def add_value(): for i in range(1, 3): print('第%s次循环' %i) d = {'age', i} print(d) print('#' * 10) print(l) print('#' * 10) l.append(d) print(l) add_value() 第1次循环 {1, 'age'} ########## [] ########## [{1, 'age'}] 第2次循环 {2, 'age'} ########## [{1, 'age'}] ########## [{1, 'age'}, {2, 'age'}]

 

l = []
def add_value(): for i in range(1, 3): d = {} print('第%s次循环' %i) d['age'] = i print(d) print('#' * 10) print(l) print('#' * 10) l.append(d) print(l) add_value() 第1次循环 {'age': 1} ########## [] ########## [{'age': 1}] 第2次循环 {'age': 2} ########## [{'age': 1}] ########## [{'age': 1}, {'age': 2}]

   总得来说就是在操做可变对象的时候,只要有 = 就会从新开辟内存建立新变量,诸如list.append() 、list += 、list.pop、dic.update()、dict['key'] = value、实际上都是在原来变量的基础上做修改,若是后面再次引用则会引用每次修改后的值。

  

a = []
b = [] c = {} d = {} e = 'frank' f = 'frank' print(id(a), id(b), id(c), id(d), id(e), id(f))

43770760 43770824 31284896 31284968 31302408 31302408

   可见每次建立一个空的可变对象时,都会从新开辟内存,但不可变对象就是指向原来的的地址空间。spa

相关文章
相关标签/搜索