1. 前言
之前有个困惑,Python 到底传的是值还是引用?不管在哪门编程语言,可能都会遇到类似的问题。Python 中究竟传的是值还是引用呢?本文将主要介绍今日所学:
- Python 中的变量和 C 中变量的区别,从而解答 Python 中到底是值传递还是引用传递
- Python 中 is 和 == 的区别?
2. C 中的变量 VS Python 中的变量
在静态语言 C 语言中,变量是代表一个地址,它相当于某个内存地址的别名,它可以用来存储指定的数据类型。C 中创建一个变量必须先声明变量的类型,看下面的例子:
# include<stdio.h>
int main(void)
{
int a = 1024;
printf("address of a = %p\n", &a);
printf("value of a = %d\n", a);
a = 520;
printf("address of a = %p\n", &a);
printf("value of a = %d\n", a);
return 0;
}
/*
address of a = 000000000061FE1C
value of a = 1024
address of a = 000000000061FE1C
value of a = 520
/*
可以看到 C 语言中,定义一个变量时必须声明变量的类型,以便于分配相应的内存空间给变量,比如 int a = 1024 ,那么变量 a 就是 int 类型,在 a 的整个生命周期中,a 的类型和内存大小都是固定的,但是内存里面值的大小是可以改变的。如果这时设置 a = 520 ,那么 a 这个内存地址存储的值就会变为 520,但是类型和内存地址不变。
我们在看一下 Python 中的情况:
>>> a = 1024
>>> print(hex(id(a)))
0x232643e01d0
>>> a = 520
>>> print(hex(id(a)))
0x232643e0290
id()
函数是查看对象的内存地址的,可以看到,在 Python 中,变量 a 的地址发生了变化。为什么会这样呢?
因为在 Python 中,变量只是个名字,它相当于 C 语言中的指针,它存储的是对象的内存地址,它指向的内存地址存储的才是真正的对象。所以 Python 中变量是对象的指针!
在 Python 中,不需要声明变量的类型,那么Python 解释器怎么知道分配多少内存呢?答案是靠猜,Python 中创建一个对象的同时你必须先赋值,Python 就是通过你赋的初值来推断这个变量指向的数据类型是什么。所以 Python 是先创建值,这个值对应一个 C 中的结构体,当创建完值后,再将变量指向这个值所在的内存地址。如:a = 1024,在 Python 中会先开辟一块内存,存储 1024,然后将变量 a 指向这块内存地址,换而言之就是让变量 a 成为这块内存地址的指针。当 a = 520 时,在 Python 中会再开辟一块内存,然后将 520 存进去,再将 变量 a 指向 520 所在的内存地址,因为两块内存不同,所以它们地址不同。1024 所在的内存,如果没有变量指向它,那么这块内存将被解释器回收。
这个关系如下图:
接下来回答一开始的问题,Python 中到底是传值还是传引用?准确的回答是:Python 中变量之间是赋值传递,对象之间是引用传递
。我们来看一个例子:
>>> a = 1024
>>> b = a
>>> print(hex(id(a)), hex(id(b)))
0x232643e01f0 0x232643e01f0
可以看到,a 和 b 指向的是同一个内存地址,或者说同一个对象。具体的行为就是 a = 1024,Python 会先开辟一块内存,存储1024,然后将这块内存的地址,即指针赋值给变量 a,所以变量 a 里面实际上存的就是 1024 的内存地址,当 b = a 时,会被 a 存储的内存地址赋值(拷贝)给 变量 b ,这样 变量 b 也指向了 1024 所在的内存地址。通俗点说,就相当于 a 和 b 两个标签都贴在了对象 1024 上。如下图所示:
另外还有一点需要注意,id(a) 获得的不是变量 a 的地址,而是变量 a 指向的对象的内存地址,也就是 变量 a 的值!实际上,变量 a 也是有地址的,只是在 Python 中不可见,Python 解释器只让你看到对象的地址。
3. is VS ==
弄明白Python中的变量之后,我们看常见的面试题, is 和 == 的区别?
答案:
is 比较的是两个对象的内存地址,== 比较的是两个对象的值是否相同。
编程实践中我们通常用的是 ==,通常我们只有在比较 None 时用 is。
>>> a, b = 2048, 2048
>>> print(a is b)
False
>>> print(a == b)
True
>>> if a is None: # 推荐
... print("good")
...
>>> if a == None: # 不推荐
... print("bad")
...