Python:变量不必要的变化发生
可能重复的问题:
Python中的“最少惊讶”原则:可变默认参数
好吧,基本上我有这段代码:
# Our Rule type.
class Rule(object):
"""An object to represent a rule and include
methods to apply these rules."""
def __init__(self,bind="F",rule=["F"]):
self.bind = bind
self.rule = rule
def show(self):
try:
print self.bind
#print self.rule
for i in range(len(self.rule)):
print self.rule[i]
except:
print "Incomplete"
def inflate(self,seq):
for i in range(len(seq)):
if seq[i] == self.bind:
seq[i] = self.rule
elif type(seq) == type(["X"]):
seq[i] = self.inflate(seq[i])
return seq
def inflate_depth(self,seq,depth):
while depth > 0:
seq = self.inflate(seq)
depth = depth - 1
print self.rule
return seq
我用这段代码从另一个文件调用它:
pity = Rule(rule=["R","F","L","F","L","F","R","F"])
seq = ["F"]
inf = pity.inflate_depth(seq,2)
所以,我应该得到一个看起来像这样的列表:
[['R', [...], 'L', [...], 'L', [...], 'R', [...]]]
这似乎工作得很好,但其实有一个根本性的错误。
self.rule
这个变量被改变成了 ['R', [...], 'L', [...], 'L', [...], 'R', [...]]
为什么呢?我根本没有在任何地方给这个变量赋新值,但它却发生了变化。
4 个回答
2
默认参数在函数定义的时候只会被计算一次,以后调用这个函数时会重复使用这个值。
def f(x, a = [])
a.append(x)
return a
print f(0)
print f(1)
打印输出
[0]
[0, 1]
通常避免这个问题的方法是把默认参数设置为 None
:
def f(x, a = None):
if a is None:
a = []
# ...
想要更详细的解释,可以查看 Python教程。
2
我不确定这是不是问题,但在像这样的函数中设置默认列表时,你需要非常小心:
def __init__(self,bind="F",rule=["F"]):
self.bind = bind
self.rule = rule
每次你调用这个函数,它都会使用同一个列表!所以,每当你在一个规则对象中修改 self.rule
时,你实际上是在修改所有其他对象中的这个列表。
相反,你应该这样做:
def __init__(self,bind="F",rule=None):
self.bind = bind
if not rule:
self.rule = ['F']
else:
self.rule = rule
这样,每次调用时你都会创建一个新的列表,而不是重复使用同一个列表。
举个例子:
class foo:
def __init__(self, x=[]):
self.x = x
self.x.append(3)
d = foo()
e = foo()
f = foo()
print f.x # prints [3,3,3]
2
我不太确定,但我觉得问题可能出在Python中的变量是引用而不是值。也就是说,当你写 seq[i] = self.rule
的时候,seq[i]
实际上是指向 self.rule
在内存中的位置。如果你改变了 seq[i]
的值,实际上也会改变 self.rule
的值,因为它们在内存中存储的是同一个地方。
你可能需要做的是深拷贝 self.rule
的值到 seq[i]
,而不是直接赋值,这样它们就会使用两个不同的内存地址来存储各自的值(想了解更多可以查看 http://docs.python.org/library/copy.html)。这样一来,给 seq[i]
赋值就不会影响到 self.rule
了。