知识点:python中,万物皆对象。
python中不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传址。
一、可变对象和不可变对象
Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容可变,而不可变对象是指对象内容不可变。
不可变(immutable):int、字符串(string)、float、(数值型number)、元组(tuple)
可变(mutable):字典型(dictionary)、列表型(list)、set
不可变类型特点:
例1:
i = 73
i += 2
从上图可知,不可变对象的特征没有变,变的只是创建了新对象,改变了变量的对象引用。
例2:
>>>x = 1
>>>y = 1
>>>x = 1
>>> x is y
True
>>>y is z
True
如上所示,因为整数为不可变,x,y,z在内存中均指向一个值为1的内存地址,也就是说,x,y,z均指向的是同一个地址,值得注意的是,整形来说,目前仅支持(-1,100)。
总结一下,不可变对象的优缺点。
优点是,这样可以减少重复的值对内存空间的占用。
缺点呢,如例1所示,我要修改这个变量绑定的值,如果内存中没用存在该值的内存块,那么必须重新开辟一块内存,把新地址与变量名绑定。而不是修改变量原来指向的内存块的值,这回给执行效率带来一定的降低。
可变对象特点:
例:
m=[5,9]
m+=[6]
二、函数参数:
函数参数都是引用。不同的在于引用后,改变变量值的时候是否会开辟新的内存空间。
Python函数参数对于可变对象,函数内对参数的改变会影响到原始对象;对于不可变对象,函数内对参数的改变不会影响到原始参数。原因在于:
1、可变对象,参数改变的是可变对象,其内容可以被修改。
2、不可变对象,改变的是函数内变量的指向对象。改变变量的值是新开辟一块内存空间,把变量指向到新的内存空间。
# -*- coding: utf-8 -*-
def func(m):
print('inner func *****')
print('m = ', m)
print('id(m): ', id(m))
m += 1
print('after add')
print('m = ', m)
print('id(m): ', id(m))
print(m)
print('end func *******')
return m
a = 10
print('a = ', a)
print('id(a): ', id(a))
func(a)
print('a = ', a)
print('id(a): ', id(a))
输出:
('a = ', 10)
('id(a): ', 19329632)
inner func *****
('m = ', 10)
('id(m): ', 19329632)
after add
('m = ', 11)
('id(m): ', 19329608)
11
end func *******
('a = ', 10)
('id(a): ', 19329632)
可以看出 函数参数是不可变对象的时候,参数依然是引用。但是改变参数的值后,开辟了新的空间存新值,函数内部的变量指向了新的内存。但是本来的值并没有变。