Python添加到字典中的意外列表[重复]
Posted
技术标签:
【中文标题】Python添加到字典中的意外列表[重复]【英文标题】:Python adding to unintended list in a dictionary [duplicate] 【发布时间】:2022-01-19 10:49:27 【问题描述】:想知道是否有人可以向我解释为什么会发生这种情况。
class Animal:
def __init__(self, name='', child=[]):
self.name=name
self.child=child
val = []
dog = Animal(name="Foo")
val.append(dog.__dict__)
cat = Animal(name='John')
cat.child.append('Doe')
val.append(cat.__dict__)
print(val)
结果:
['name': 'Foo', 'child': ['Doe'], 'name': 'John', 'child': ['Doe']]
预期:
['name': 'Foo', 'child': [], 'name': 'John', 'child': ['Doe']]
我假设它与内存分配有关,但我无法理解它是如何工作的。
提前致谢!
【问题讨论】:
不要使用像child=[]
这样的可变默认参数
【参考方案1】:
字典是引用类型变量。引用是指一个值(对象)在内存中的特定位置的名称。这意味着在您实例化一个 dict 后,它总是指向内存中的相同位置。无论您是否编辑您的字典。所以一个简单的代码解决方案是:
class Animal:
def __init__(self, name='', child=None):
self.name=name
self.child=child
if self.child is None:
self.child = []
val = []
dog = Animal(name="Foo")
print(dog.__dict__)
val.append(dog.__dict__)
cat = Animal(name='John')
cat.child.append('Doe')
val.append(cat.__dict__)
print(val)
这样每次从 Animal 类创建对象时,它都会在内存中保留一个新位置。
【讨论】:
“字典是引用类型变量”——这有点误导。无论数据类型如何,所有 Python 名称(如果您愿意,也可以是变量)都是对内存中某个对象的单向引用。它可以是一个列表,int,dict,...与名称无关。您可能想说的是:“dicts 是可变的”。 @timgeb 是的,完全正确。 dict 是可变的,你必须完全理解 python 是如何思考和作用于“可变”的。证明这一点的简单方法是它存在于内存中,并且每次你指的是同一个地方。【参考方案2】:您可以使用数据类并为列表设置默认工厂
from dataclasses import dataclass, field, asdict
from typing import List
@dataclass
class Animal:
name : str
children : List[str] = field(default_factory=list)
a=Animal(name="Foo")
b=Animal(name='John')
b.children.append('Doe')
val = [
asdict(x) for x in [a,b]
]
print(val)
【讨论】:
以上是关于Python添加到字典中的意外列表[重复]的主要内容,如果未能解决你的问题,请参考以下文章