Python:变量不必要的变化发生

2 投票
4 回答
548 浏览
提问于 2025-04-17 05:06

可能重复的问题:
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 了。

撰写回答