python 中的可变参数和不可变参数
2017-03-30
关于此文的部分内容有些混乱与错误,请看 python 函数调用是值传递还是引用传递
可变参数 (可变对象): 列表,字典,集合
不可变参数 (不可变对象): 数字,字符串,元组
可变参数: 引用调用
不可变参数: 值调用
可变对象和不可变对象的区别是即是他们的值是否可变,如字符串是不可变的,那么在你的每一次修改值的时候,其实你得到的已经不是之前的那个字符串对象了。
>>> a = 'origin is here'
>>> id(a)
8306144
>>> a = 'change it'
>>> a
'change it'
>>> id(a)
48359904
但是对不可变对象的复制是深复制,不过当对复制内容的修改时,就变成了浅复制,对复制内容的修改并不会体现在初始内容上。
>>> a = 'origin is here'
>>> b=a
>>> id(a)
44678624
>>> id(b)
44678624
>>> b = 'change it'
>>> a
'origin is here'
>>> id(a)
44678624
>>> id(b)
45935136
还有就是在函数调用的时候,对于不可变对象的引用并不是同一个,即形参与实参并不是指向同一个地址,在形参进行修改,并不会体现在实参上。
>>> def rename(n):
... n='change it'
...
>>> a
'origin is here'
>>> rename(a)
>>> a
'origin is here'
而可变参数,形参和实参是一致的,在函数内对形参进行修改也会体现在实参上。
>>> def rename(n):
... n[0]='change it'
...
>>> a = ['origin is here', ]
>>> rename(a)
>>> a
['change it']
对可变参数的复制也是深拷贝,对可变对象的修改即是对原对象的修改。
>>> a = ['origin is here', ]
>>> b=a
>>> id(a)
45947400
>>> id(b)
45947400
>>> b[0] = 'change it'
>>> a
['change it']
>>> b
['change it']
>>> id(a)
45947400
>>> id(b)
45947400
那么如果我们就是想要对可变对象的浅复制呢?可以使用 copy
这个库,或者 列表也提供了一个浅复制的方法。
>>> a = ['origin is here', ]
>>> b=a[:]
>>> id(a)
45913672
>>> id(b)
45946200
>>> import copy
>>> c=copy.copy(a)
>>> id(c)
45999728
>>> b='change it'
>>> a
['origin is here']
>>> c='change it again'
>>> a
['origin is here']
同样的,copy
这个库也提供了深拷贝,但是还是不能修改不可变对象。
>>> a='origin is here'
>>> b=copy.deepcopy(a)
>>> id(a)
45999632
>>> id(b)
45999632
>>> b='change it'
>>> a
'origin is here'
>>> id(a)
45999632
>>> id(b)
45935072
最后,我们来深入研究一下它们之间的区别,我们就以数字,字符串,列表,元组,字典这六种类型为例探讨一下。
先来看一下它们实例所属的类和父类
# print 1.__base__ # SyntaxError
# print 'a'.__base__ # AttributeError
# print [].__base__ # AttributeError
# print ().__base__ # AttributeError
# print {}.__base__ # AttributeError
# print 1.__class__ # SyntaxError
type(1) # <type 'int'>
print 'a'.__class__ # <type 'str'>
print [].__class__ # <type 'list'>
print ().__class__ # <type 'tuple'>
print {}.__class__ # <type 'dict'>
为什么会这样,所有的实例都没有父类,或语法错误,或属性错误,但是它们都还是属于它们原始的那个类型,int 类型最为特殊,不能用 __class__
查看所属类型,不过可以使用 type
查看其类型。
那么我们查看它们所在类型的父类和所属类。
print int.__base__ # <type 'object'>
print str.__base__ # <type 'basestring'>
print str.__base__.__base__ # <type 'object'>
print list.__base__ # <type 'object'>
print set.__base__ # <type 'object'>
print dict.__base__ # <type 'object'>
print int.__class__ # <type 'type'>
print str.__class__ # <type 'type'>
print set.__class__ # <type 'type'>
print list.__class__ # <type 'type'>
print dict.__class__ # <type 'type'>
虽然 str 的直接父类并不是 object ,不过它的最终父类还是 object ,所以也就是所有的类型的最终父类都是对象,即 一切皆对象, 或者 一切都是对象的子类。
但是为什么所有的类型的当前类是 type ,type 是什么?
print isinstance(1, object) # True
print isinstance('a', object) # True
print isinstance([], object) # True
print isinstance((), object) # True
print isinstance({}, object) # True
print isinstance(int, object) # True
print isinstance(str, object) # True
print isinstance(list, object) # True
print isinstance(set, object) # True
print isinstance(dict, object) # True
print isinstance(type, object) # True
不管你现在是个什么玩意儿,都是 object 的实例,你的类都是直接或间接继承自 object。
但是还是不太明白 type 是什么, type 到底是从何处来,为什么在查看所有的类型的时候,它的类型都是 <type XXX>
。
看一下 type 的父类和类
print type.__base__ # <type 'object'>
print type.__class__ # <type 'type'>
type 的父类是 object ,现在的类就是 type ,它也是继承自 object ,但是它和 object 到底是什么关系呢?
type 和 object 的关系与 可变对象和不可变的关系 有联系么?
暂时还不是很清楚,关于 type 和 object 的关系可以参看这篇文章。
本文固定链接:https://windard.com/blog/2017/03/30/Mutable-And-Immutable-Parameter
原创文章,转载请注明出处:python 中的可变参数和不可变参数 By Windard