.append()之后,唯一数据不再唯一

时间:2019-04-18 08:14:31

标签: python

已编辑。该示例现已完全可复制。

我陷入了一个我不应该陷入的问题,使用一种熟悉的模式。我生成一些随机数据,通过打印三个 distinct 行向我证明自己是随机的,将随机数据附加到列表中,然后-所得列表中的行都相同。

from random import randint

fields = [
    {"foo": "bar"},
]


def some_randomizing_func(adict):
    adict["number"] = randint(0, 1000)
    return adict


rows = []
for ith in range(3):
    row = [some_randomizing_func(field) for field in fields]
    print("BEFORE ", row)  # Proves they are unique at this point
    rows.append(row)  # Therefore each list in this list should also be unique

print("AFTER ", rows)  # But they're not!

将其作为脚本运行即可:

BEFORE  [{'foo': 'bar', 'number': 306}]
BEFORE  [{'foo': 'bar', 'number': 943}]
BEFORE  [{'foo': 'bar', 'number': 230}]

AFTER  [
    [{'foo': 'bar', 'number': 230}],
    [{'foo': 'bar', 'number': 230}],
    [{'foo': 'bar', 'number': 230}]
]

我已经尝试了所有可以想到的方法-使用带数字键的字典而不是列表,使用fields.copy(),使用enumerate()和计数器并分配给列表索引,但是问题仍然存在。在附加后,row在第一个print()期间如何证明自己是唯一的,而在第二个print()以后又不再唯一的呢?

更新:可以通过将append()行更改为

来解决此问题

rows.append(copy.deepcopy(row))

但是我不明白为什么为什么可以解决此问题,并且感觉它正在解决实际问题。

2 个答案:

答案 0 :(得分:0)

我相信您的函数class App extends React.Component { //... render() { const { data } = this.state; return ( <div> <ChildComponent data={data} /> </div> ); } } //for array, ex: data = ["first","name"]; class ChildComponent extends React.Component { render() { return ( <React.Fragment> {this.props.data.map(item => <p>{item}</p> )} </React.Fragment> ); } } //for object, ex: data = {id: 1, name: 'John'}; class ChildComponent extends React.Component { render() { const {data} = this.props; return ( <React.Fragment> <p>{data.id}</p> <p>{data.name}</p> </React.Fragment> ); } } //for single value (string, int, etc), ex: data = "my name"; class ChildComponent extends React.Component { render() { return ( <React.Fragment> <p>{this.props.data}</p> </React.Fragment> ); } } //to show object as a string (could be any object mentioned before) class ChildComponent extends React.Component { render() { return ( <React.Fragment> {JSON.stringify(this.props.data)} </React.Fragment> ); } } 函数具有某种副作用,即返回的每个列表实际上都指向同一列表对象。 这是您应该调查的。

但是,作为一种快速解决方案,您可以使用some_randomizing_func来拥有copy.deepcopy的独立副本,这样可以避免任何副作用。

row

请注意,深层副本的缺点是它会增加RAM消耗。 您可能会找到更好的方法来解决此问题。

答案 1 :(得分:0)

感谢@rightleg和其他人的评论,这是关键要点:

“因此,在循环之后,尽管行都是不同的对象,但它们都包含 same 对象。”因此,可以通过在随机函数中复制字典来解决问题,而无需使用deepcopy()

def some_randomizing_func(somedict):
    newdict = somedict.copy()
    newdict["number"] = randint(0, 1000)
    return newdict