知识点:python中,万物皆对象。

python中不存在所谓的传值调用,一切传递的都是对象的引用,也可以认为是传址。

一、可变对象和不可变对象
Python在heap中分配的对象分成两类:可变对象和不可变对象。所谓可变对象是指,对象的内容可变,而不可变对象是指对象内容不可变。

不可变(immutable):int、字符串(string)、float、(数值型number)、元组(tuple)

可变(mutable):字典型(dictionary)、列表型(list)、set

不可变类型特点:

例1:

i = 73
i += 2

python可变和不可变类型 python 可变与不可变_函数参数


从上图可知,不可变对象的特征没有变,变的只是创建了新对象,改变了变量的对象引用。

例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可变和不可变类型 python 可变与不可变_函数参数_02

二、函数参数:
函数参数都是引用。不同的在于引用后,改变变量值的时候是否会开辟新的内存空间。
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)

可以看出 函数参数是不可变对象的时候,参数依然是引用。但是改变参数的值后,开辟了新的空间存新值,函数内部的变量指向了新的内存。但是本来的值并没有变。