深刻理解python变量

Posted 詩和遠方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深刻理解python变量相关的知识,希望对你有一定的参考价值。

概述

  • python的标识符更像C++中的指针或JAVA中的引用变量,每个标识符与其所指向的内存地址相关联
  • 像 b = a 这样赋值语句,就是为 a 起了一个别名 b,id(a)与id(b)是相等的
  • python函数传参,传的也是引用

下面分情况举例说明,重点看注释说明。

不可变类型

a = 1
print(id(a))
b = a
print(id(b))   # 仅仅是别名,id(a)与id(b) 是一样的
140717113381696
140717113381696
a = a + 4
print(a)
print(id(a))   # a+4会产生新实例,a指向了新的内容,id已变
13
140717113382080
print(b)       
print(id(b))   # b指向的还是原来的内容,id不变
1
140717113381696
b = b + 4
print(b)
print(id(b))   # b的值变为与a一样,此时可能是为了节约内存,指向的是同一个实例,id不变 
5
140717113381824
a = a + 2      
print(id(a))   # a的值与b不等,指向不同实例,id已变
140717113382144

可变类型

ls = [1,2,3]
print(id(ls))

lt = ls
print(id(lt))  # 仅仅是别名,id(a) 与 id(b) 是一样的
2606652175432
2606652175432
ls[1] = 9
print(ls)
print(id(ls))  # 此操作改变了 ls 的值,由于 list 是可变类型,支持就地更新,故地址不变,即 id 不变
[1, 9, 3]
2606652175432
print(id(lt))  # lt也是指向相同地址,故ls的修改,就是lt的修改,id不变,内容已变
print(lt)
2606652175432
[1, 9, 3]
ls = list(range(5)) 
print(id(ls))  # ls 指向新的 list 实例,id已变
2606658295816
print(id(lt))
print(lt)      # lt仍维持原样
2606652175432
[1, 9, 3]

函数传参为引用

def punctuation_remove(my_str):
    print('【inside function】',id(my_str))  # my_str未改变时的id值,与所传参数id值一致
    from string import punctuation
    for p in punctuation:
        if p in my_str:
            my_str = my_str.replace(p,'')    # str不可变类型,my_str每次指向新的实例
            print('【inside function】After Change:',id(my_str))
    return my_str
x = "let's play a game?"
print('【outside functoin】',id(x))
【outside functoin】 2606657730720
punctuation_remove(x)
【inside function】 2606657730720
【inside function】After Change: 2606657728848
【inside function】After Change: 2606657728704
'lets play a game'

以上可以发现函数内参数最初的id值与外层传入时是一致的,故相当于传引用

以上是关于深刻理解python变量的主要内容,如果未能解决你的问题,请参考以下文章

深刻理解Python中的元类(metaclass)

深刻理解Python中的元类(metaclass)

python基础装饰器

深刻理解Python中的元类(metaclass)

深刻理解Python中的元类(metaclass)

深刻理解Python中的元类(metaclass)