【问题标题】:Python: List handling in functionsPython:函数中的列表处理
【发布时间】:2015-07-15 01:46:08
【问题描述】:

抱歉,我无法更好地描述问题名称 - 我真的不知道问题可能是什么,因此我不能非常具体。

在 Python 中,我有以下代码:

# input
list_environments = ["tree", "bush"]
list_fruit = ["banana", "kiwi"]
list_properties = [
                   ["_size", [["width"], ["height"], ["depth"]]],
                   ["_colour", [["rgb_r"], ["rgb_g"], ["rgb_b"]]],
                   ["_shape", [["is_round"], ["is_square"], ["is_flat"]]]
                   ]

# create list of all combinations: [environment, fruit, properties set]
list_combinations = []
for env in list_environments:
    for fruit in list_fruit:
        for prop in list_properties:
            list_combinations.append([env, fruit, prop])

# define function
def process_entry(inp_environment, inp_fruit, inp_property):

    # print data at start of function
    print(".")
    print("Dataset before processing:", inp_environment, inp_fruit, inp_property)

    # - create temporary list for property value pairs -
    tmp_list = inp_property[1] # takes only the sublist from property list

    # add info for size
    if inp_property[0] == "_size":
        tmp_list[0].append(1) # width is 1 
        tmp_list[1].append(2) # height is 2
        tmp_list[2].append(3) # depth is 3
    # add info for colour
    elif inp_property[0] == "_colour":
        tmp_list[0].append(100) # r-value is 100
        tmp_list[1].append(101) # g-value is 101
        tmp_list[2].append(102) # b-value is 102
    # add info for shape 
    elif inp_property[0] == "_shape":
        tmp_list[0].append(0) # is not round
        tmp_list[1].append(0) # is not square
        tmp_list[2].append(1) # is flat

    print("Dataset now:", inp_environment, inp_fruit, tmp_list)    

# call processing function for every entry in combination list
for entry in list_combinations:
    process_entry(entry[0], entry[1], entry[2])

我现在所期望的是,该函数将在最后将(静态)值分配给 for 循环的每个组合。相反,分配的值保留在属性列表中,并且输出总是被另一个值集扩展。输出如下所示:

.
Dataset before processing: tree banana ['_size', [['width'], ['height'],['depth']]]
Dataset now: tree banana [['width', 1], ['height', 2], ['depth', 3]]
.
Dataset before processing: tree banana ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]
Dataset now: tree banana [['rgb_r', 100], ['rgb_g', 101], ['rgb_b', 102]]
.
Dataset before processing: tree banana ['_shape', [['is_round'], ['is_square'], ['is_flat']]]
Dataset now: tree banana [['is_round', 0], ['is_square', 0], ['is_flat', 1]]

-> 到目前为止,第一次循环遍历属性后一切正常。

现在...:

Dataset before processing: tree kiwi ['_size', [['width', 1], ['height', 2], ['depth', 3]]]
Dataset now: tree kiwi [['width', 1, 1], ['height', 2, 2], ['depth', 3, 3]]
.
Dataset before processing: tree kiwi ['_colour', [['rgb_r', 100], ['rgb_g', 101], ['rgb_b', 102]]]
Dataset now: tree kiwi [['rgb_r', 100, 100], ['rgb_g', 101, 101], ['rgb_b', 102, 102]]
.
Dataset before processing: tree kiwi ['_shape', [['is_round', 0], ['is_square', 0], ['is_flat', 1]]]
Dataset now: tree kiwi [['is_round', 0, 0], ['is_square', 0, 0], ['is_flat', 1, 1]]

现在出了问题:第一个属性循环中的值仍然存在,并且属性子列表得到扩展。这真的很奇怪,因为我认为由于我之前创建的组合列表,我为函数提供了一个“新鲜”的数据集来使用。有谁知道我的错误在哪里?

提前致谢!

【问题讨论】:

    标签: python list function


    【解决方案1】:

    问题是这一行:tmp_list = inp_property[1]。这只是为现有列表提供了一个新名称,然后您继续修改它,从而修改原始列表。实际上问题更深一层,因为您随后会附加到子列表。要解决此问题,只需导入复制模块并将其更改为 tmp_list = copy.deepcopy(inp_property[1])

    【讨论】:

    • 谢谢您-从您和布鲁诺的回答中,我已经能够解决它! :-) 我在函数调用之前应用了复制——正如 mhawke 也指出并在后面建议的那样。
    【解决方案2】:

    这个:

    tmp_list = inp_property[1]
    

    不会将inp_property[1] 复制到tmp_list,它只是使tmp_list 指向与inp_property[1] 相同的对象。所以修改tmp_list和修改inp_property[1]是一样的。

    当您将entry[2] 传递给process_entry() 时,同样的事情 - process_entry() 不会获得entry[2] 的副本,它会获得对名为 @ 的 same 对象的引用987654332@,所以修改inp_property[1]与修改entry[2][1]相同——与修改list_combinations[i][2][1]相同(对于'i' = for循环中的当前迭代)。

    【讨论】:

    • 谢谢你,Bruno - 你对各种修改选项的解释(最终都是修改相同的东西)非常好:-)
    【解决方案3】:

    其他答案强调了tmp_list 是对同一列表的引用,而不是副本的问题,您可以在函数process_entry() 中使用tmp_list = copy.deepcopy(inp_property[1]) 来处理单独的副本。

    但值得一提的是,在初始化 list_combinations 之后,所有属性列表实际上是同一个列表 - 与使用对 list_properties 的引用的原因相同,不是副本。在初始化后立即考虑list_combinations 的值:

    >>> from pprint import pprint
    >>> pprint(list_combinations)
    [['tree', 'banana', ['_size', [['width'], ['height'], ['depth']]]],
     ['tree', 'banana', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['tree', 'banana', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]],
     ['tree', 'kiwi', ['_size', [['width'], ['height'], ['depth']]]],
     ['tree', 'kiwi', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['tree', 'kiwi', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]],
     ['bush', 'banana', ['_size', [['width'], ['height'], ['depth']]]],
     ['bush', 'banana', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['bush', 'banana', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]],
     ['bush', 'kiwi', ['_size', [['width'], ['height'], ['depth']]]],
     ['bush', 'kiwi', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['bush', 'kiwi', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]]]
    

    如果属性子列表之一发生更改,该更改将影响list_combinations 中的所有条目:

    >>> list_combinations[0][2][1][0].append('hi there')
    >>> pprint(list_combinations)
    [['tree', 'banana', ['_size', [['width', 'hi there'], ['height'], ['depth']]]],
     ['tree', 'banana', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['tree', 'banana', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]],
     ['tree', 'kiwi', ['_size', [['width', 'hi there'], ['height'], ['depth']]]],
     ['tree', 'kiwi', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['tree', 'kiwi', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]],
     ['bush', 'banana', ['_size', [['width', 'hi there'], ['height'], ['depth']]]],
     ['bush', 'banana', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['bush', 'banana', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]],
     ['bush', 'kiwi', ['_size', [['width', 'hi there'], ['height'], ['depth']]]],
     ['bush', 'kiwi', ['_colour', [['rgb_r'], ['rgb_g'], ['rgb_b']]]],
     ['bush', 'kiwi', ['_shape', [['is_round'], ['is_square'], ['is_flat']]]]]
    

    因此解决此问题的另一种方法是在初始化时复制 list_properties 中包含的列表:

    from copy import deepcopy
    
    list_combinations = []
    for env in list_environments:
        for fruit in list_fruit:
            for prop in list_properties:
                list_combinations.append([env, fruit, deepcopy(prop)])
    

    【讨论】:

    • 谢谢,非常有助于了解更改对所有列表的影响!
    猜你喜欢
    • 2012-07-27
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多