python中一切皆对象
首先我们来看一个例子,可以在IDLE中输入以下代码:
a = 1
b = 1
id(a) == id(b) == id(1)
通过这个例子,我们可以推断出,a和b是指向同一个空间的,即1所在的空间
再看一个例子
a = 1
b = 1
b = a + 1
id(a) == id(b)
结果为False,b = a + 1,这里我们需要明白一点,那就是python中int类型、float类型是不可变的。
什么是不可变?
以该例为例,第一行语句a = 1
在内存中创建一个值为1的对象,通过a变量来引用该对象
第二行语句b = 1
,创建了一个b变量,该变量和变量a指向同一个对象
第三行语句b = a + 1
,因为python中int类型的变量是不可变的,所以,该语句会创建一个值为a+1的对象,即一个值为2的对象,然后通过b来引用该对象
搞明白这些后,接下来我们来看python中的参数传递
python中的参数传递
有一个函数,它的定义如下
def f1(a):
a = a + 1
通过以下语句调用它
a = 1
f1(a)
请问,a的值是多少?a的值还是1,如果按照c语言的想法来说的话,居然a是引用,那么把a传递给函数形参,形参的值改变了,实参的值也会改变,为什么这个函数不会这样呢?
原因是,python中int类型是不可变的。当通过f1(a)
调用函数时,实参a指向的对象确实被传递给了函数f1(),但我们来看f1的函数体
a = a + 1
通过上文,我们已经知道int类型是不可变的,所以该函数体执行后,形参a和实参a实际指向的就不是一个空间了。当刚调用函数f1时,语句f1(a)
把实参a的引用传递给了函数f1,此时实参a和形参a指向同一段空间
在执行a = a + 1
这段语句时,因为int类型是不可变的,所以,会创建一个新对象,由形参a来引用它
此时,实参a和形参a指向对象已经不同了,所以无论形参a如何变化都不会影响到实参a。如果想让形参a的变化能够影响到实参a的话,可以修改函数体如下所示
def f1(a):
a = a + 1
return a
然后通过a = f1(a)
调用函数即可
注意,这是不可变类型当作实参进行传递时的情况,接下来让我们看一看可变类型当作实参进行传递的情况。
有如下函数
def f1(a):
for i in range(len(a)):
a[i] = a[i] + 1
通过如下语句调用函数f1
a = [1, 2, 3, 4, 5]
f1(a)
请问,a列表中的值会发生变化吗?
答案是会的,为什么呢?因为列表是可变的,修改可变类型的对象的值时,不会创建新对象
通过f1函数会将图中上面的值(即列表原来的值)修改为下面的值(即更改后的值)
总结
- python中一切皆对象
- python中的参数传递都是把实参指向的对象传递给形参,但具体是否会影响实参取决于调用方式和对象类型是否可变