变量保存的是引用,这一点对 Python 编程有很多实际的影响。
简单的赋值不创建副本。
举例:
a = 1
对 += 或 *= 所做的增量赋值来说,如果左边的变量绑定的是不可变
对象,会创建新对象;如果是可变对象,会就地修改。
举例:
a = [1,2,3]
b = a
a += [1] [1,2,3,1]
a is b # True
a = (2,3)
b = a #(2,3)
a += (1,) # (1,2,3)
a is b # False
为现有的变量赋予新值,不会修改之前绑定的变量。这叫重新绑
定:现在变量绑定了其他对象。如果变量是之前那个对象的最后一
个引用,对象会被当作垃圾回收。
a = 1 # a = 1
b = a # b = 1
a = 3 # a = 3 这个叫做重新绑定
# 如果a = 4 这个时候3这个对象就会被回收.
函数的参数以别名的形式传递,这意味着,函数可能会修改通过参
数传入的可变对象。这一行为无法避免,除非在本地创建副本,或
者使用不可变对象(例如,传入元组,而不传入列表)。
class HauntedBus:
def __init__(self, passengers=[]):
self.passengers = passengers
def pick(self, name):
self.passengers.append(name)
def drop(self, name):
self.passengers.remove(name)
bus1 = HauntedBus(['alice', 'bill'])
print bus1.passengers #['alice','bill']
bus1.pick('charlie')
bus1.drop('alice')
print bus1.passengers #['bill', 'charlie']
# ------------------关键点-----------------
bus2 = HauntedBus() #bus2是空的,因此把默认的空列表赋值给self.passengers
bus2.pick('Carrie')
bus2.passengers # ['Carrie']
bus3 = HauntedBus() # bus3也是空的,因此用的也是默认列表.但是这个时候,默认的列表不为空!
print bus3.passengers # ['Carrie']
bus3.pick('Dave')
bus2.passengers # ['Carrie', 'Dave']
bus2.passengers is bus3.passengers # True
使用可变类型作为函数参数的默认值有危险,因为如果就地修改了
参数,默认值也就变了,这会影响以后使用默认值的调用。
class TwilightBus:
def __init__(self, passengers=None):
if passengers is None:
self.passengers = [] #当passengers为None时,创建一个新的空列表
else:
self.passengers = passengers #然而,这个赋值语句把self.passengers 变成 passengers 的别名,而basketball_team是传递给__init__方法的实参.
def pick(self, name):
self.passengers.append(name) #相当于对列表进行了操作!!!
def drop(self, name):
self.passengers.remove(name) # 相当于对列表进行了操作!!!
basketball_team = ['Sue', 'Tina', "Maya", "Diana", "Pat"]
bus = TwilightBus(basketball_team)
bus.drop('Tina')
bus.drop("Pat")
print basketball_team #['sue','Maya','Diana']
1000

被折叠的 条评论
为什么被折叠?



