python - 构造函数参数重新用于新对象?

标签 python

<分区>

我是 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()方法在主程序中第二次调用 kvals KeyValList 的参数构造函数包含前对。但这怎么可能呢?我不为此提供任何信息 kvals参数,由于参数的默认值,因此不应该将其初始化为空列表吗?

PS:我在 Windows 上使用 Python 2.7.3。

最佳答案

这基本上是 Python 的一个非常常见的——一开始相当违反直觉的——特性的实例,mutable default argument .要点是默认参数是函数对象的属性,因此如果您在一个函数调用中改变它们,您会为所有函数调用改变它们。

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

换句话说,当你写

self.kvals.append(...)

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

关于python - 构造函数参数重新用于新对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16125772/

相关文章:

Python执行复杂的shell命令

python - 应用函数并返回多个数据帧后重命名系列列名称

python - Wagtail/Django block 无法从自定义/嵌套 StructBlock 模板正确呈现内容

python - django外部应用程序安装 "Error: No module named nested-inlines"

python - 在 C++/Obj-C++ 中运行 Tensorflow 分类器模型导致与 Python 不同的结果

python - GAE : remote_api_shell. py 使用了错误的 Django 版本

python - 语法错误 : invalid syntax in mfs. cgi

python - 如何使用geojson和shapely确定一个点是否在多边形内部

Python进程和MySQL

python - 使用 c_iso_binding 和 cython 用 fortran 创建一个 python 包