Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 构造函数参数是否重新用于新对象?_Python - Fatal编程技术网

Python 构造函数参数是否重新用于新对象?

Python 构造函数参数是否重新用于新对象?,python,Python,我是Python新手,在使用它编写一个小应用程序时遇到了一个问题。由于我在谷歌上找不到类似的东西,我可能误解了Python的一些基本概念。如果你们中有人能向我解释一下,那就太好了 下面是一个简单的工作示例。请忽略类和变量名,这只是一个人工示例,但它显示了我的意思。您可以将其c&p到您的IDE并自己运行它 class State(object): def __init__(self, wrappers = []): self.wrappers = wrappers

我是Python新手,在使用它编写一个小应用程序时遇到了一个问题。由于我在谷歌上找不到类似的东西,我可能误解了Python的一些基本概念。如果你们中有人能向我解释一下,那就太好了

下面是一个简单的工作示例。请忽略类和变量名,这只是一个人工示例,但它显示了我的意思。您可以将其c&p到您的IDE并自己运行它

class State(object):
    def __init__(self, wrappers = []):
        self.wrappers = wrappers

    def add(self, name, items):
        lst = KeyValList(name)
        for item in items:
            lst.add(item, items[item])
        self.wrappers.append(Wrapper(lst))

class Wrapper(object):
    def __init__(self, kv_lst):
        self.kv_lst = kv_lst

class KeyValList(object):
    def __init__(self, name, kvals = []):
        self.name = str(name)
        self.kvals = kvals

    def add(self, key, value):
        self.kvals.append(KeyVal(key, value))

class KeyVal(object):
    def __init__(self, key, val):
        self.key = str(key)
        self.val = val
好的,这就是我使用的类的定义。
我在下面写了以下内容:

state = State()
kv = { "key1" : "1", "key2" : "2", "key3" : "3" }
state.add("1st", kv)
kv = { "keyX" : "X", "keyY" : "Y", "keyZ" : "Z" }
state.add("2nd", kv)

for wrap in state.wrappers:
    print wrap.kv_lst.name, "-->",
    for kv in wrap.kv_lst.kvals:
        print "%s:%s" % (kv.key, kv.val),
    print ""
作为一名Java程序员,我希望得到以下结果:

1st --> key3:3 key2:2 key1:1
2nd --> keyZ:Z keyY:Y keyX:X
但是,使用Python中的此程序,我得到了以下输出:

1st --> key3:3 key2:2 key1:1 keyZ:Z keyY:Y keyX:X 
2nd --> key3:3 key2:2 key1:1 keyZ:Z keyY:Y keyX:X 
为什么两个列表都包含所有键/值对

我预计问题会出现在
KeyValList
类的某个地方,因为在主程序中第二次调用
state.add()
方法时,
KeyValList
构造函数的
kvals
参数包含前面的对。但这怎么可能呢?我没有为这个
kvals
参数提供任何信息,由于参数的默认值,是否应该将其初始化为空列表


PS:我在Windows上使用Python 2.7.3。

不要使用可变的默认参数,而是使用None作为占位符,并让您的函数/方法在每次调用时构造新的容器

更改此项:

class State(object):
    def __init__(self, wrappers = []):
        self.wrappers = wrappers
为此:

class State(object):
    def __init__(self, wrappers = None):
        if wrappers is None:
           wrappers = []
        self.wrappers = wrappers

关于这个问题,在中有一个很好的解释。

这基本上是Python的一个非常常见的特性的一个实例,一开始是违反直觉的。要点是,默认参数是函数对象的属性,因此,如果在一个函数调用中对其进行变异,则会对所有函数调用进行变异

这个例子比标准的可变默认参数问题稍微复杂一些,因为您还将同一个对象作为类的属性和实例传递。但是代码中只有一个列表对象,即由
[]
创建的列表对象,因此通过实例属性对其进行修改与在函数对象上修改相同

换句话说,当你写作的时候

self.kvals.append(...)

您正在将一些数据附加到特定的列表对象。哪个列表对象?函数定义中由
[]
创建的函数,因此与Python用作函数默认参数的函数相同。

谢谢,这当然解释了我的问题所在。我现在必须把它牢记在脑中,以便将来记住:)非常感谢,这对我帮助很大。您提供的链接也很好地解释了“问题”。当我读到它时,我首先认为这在Python中很奇怪,但后来解释了为什么这确实有意义。谢谢