1. Python中的变量名是没有类型信息的,这样增加了python的灵活性。
a=[1,2,3]
a="Hello"
对象[1,2,3]是List类型的,对象"Hello"是String类型的,而变量a是没有类型的,变量a仅仅是一个对象的引用(一个指针),既可以指向List类型对象,也可以指向String类型的对象。
2.
Python的参数传递既不是传值(pass-by-value),也不是传引用(pass-by-reference),而是对象的引用(pass-by-object-reference),即传递的是一个对象的内存地址。
def
reassign(list):
list = [0, 1]
def
append(list):
list.append(1)
list =
[0]
reassign(list)
append(list)
list
上面的代码首先创建了一个List对象[0],该对象的内存地址存储在list变量中。
然后调用reassign()函数,传递的是List对象[0]的内存地址。在函数中,list变量指向了新的List对象[0,1],一个新的内存地址.
原始的List对象[0]的内存地址和对象的内容并没有改变。
传递给append()函数的参数是原始List对象[0]的内存地址,然后修改了List对象的内容,List对象是可修改的(mutable),因此对象的内存地址没有变化。
输出的是list变量所指向的对象,该对象被append()函数修改了,reassign()函数没有修改该对象,所以输出为[0,1]
3. 对传递对象引用的理解:
3.1 在类的继承中的对象引用
class
Parent(object):
x = 1
class
Child1(Parent):
pass
class
Child2(Parent):
pass
Parent.x, Child1.x, Child2.x
Child1.x = 2
Parent.x, Child1.x, Child2.x
Parent.x = 3
Parent.x, Child1.x,
Child2.x
输出结果为:
1 1 1
1 2 1
3 2
3
Child1和Child2的变量x都是从Parent的变量x传递过来的,也就是Parent.x对象的引用。
3.2 在函数默认参数中的对象引用
def extendList(val,
list=[]):
list.append(val)
return
list
list1 =
extendList(10)
list2 =
extendList(123,[])
list3 = extendList('a')
print "list1 = %s" %
list1
print "list2 = %s" %
list2
print "list3 = %s" %
list3
输出的结果为:
list1 =[10, 'a']
list2 =
[123]
list3
=[10,
'a']
函数extendList(10)和extendList('a')使用的是同一个默认参数列表,函数中的list变量是空列表[]对象的引用,append()操作不改变列表的内存地址。
参考文献:
1.
http://robertheaton.com/2014/02/09/pythons-pass-by-object-reference-as-explained-by-philip-k-dick/
2.
http://segmentfault.com/a/1190000000618513