我已经读过python将所有变量赋值视为引用而不是副本。因此,下面生成3个独立列表的代码不起作用:
sizeNeeded = 4
itemDateNums = itemWeights = itemVolumes = [[]] * sizeNeeded
itemDateNums[1].append("hello world")
# All instances are now hello world because of referencing
所以我重写了代码:
sizeNeeded = 4
itemDateNums = []
itemWeights = []
itemVolumes = []
for shifts in range(sizeNeeded):
itemDateNums.append([])
itemWeights.append([])
itemVolumes.append([])
itemDateNums[1].append("hello world")
但语法看起来很冗余。是否有更清晰的方式表达需要复制分配而不是参考分配?
答案 0 :(得分:1)
没有任何需要预先初始化大小,正如上面的两位炼金术士所说的那样,但如果你知道你的大小,那么它往往是效率的。数组将会是。
查看通用copy
模块
>>from copy import copy as cp
>>a = [[] for _ in range(4)]
>>a
a = [[],[],[],[]]
>>b = cp(a)
>>a[1] = 4
>>a
a = [[],4,[],[]]
b = [[],[],[],[]]
但是你仍然需要三行:
itemDateNums = [[] for _ in range(sizeNeeded)]
itemWeights = cp(itemDateNums)
itemVolumes = cp(itemVolumes)
或者如果你真的想要两个,但它不那么漂亮:
itemDateNums = [[] for _ in range(sizeNeeded)]
itemWeights, itemVolumes = cp(itemDateNums), cp(itemDateNums)
我不确定使用标准库有更清晰的方法来实现这一点,而无需安装NumPy或类似的。但如果我发现,我会更新。
修改:另请查看copy.deepcopy
:
What exactly is the difference between shallow copy, deepcopy and normal assignment operation?
另外,正如下面提到的tobias_k 5,a = [[]]*4
不安全:
>>a = [[]]*4
>>b = [[] for _ in range(4)]
>>a[0].append(5)
>>b[0].append(5)
>>print ('a:{}\nb:{}'.format(a,b))
a: [[5], [5], [5] ,[5]]
b: [[5], [], [], []]
答案 1 :(得分:1)
请注意,您的代码存在两个问题:
x = y = z = [some list]
会为每个变量分配相同的对象。在不可变对象(如数字或字符串)的情况下,这是可以的,但不适用于列表。[[]] * number
没有达到您所期望的效果,因为结果列表将number
引用与相同的空列表,即当你追加到一个时,你会附加到所有人身上!相反,你可以尝试以下方法,使用列表推导来创建(双重嵌套)列表和元组解包,将其“分发”到变量中:
>>> itemDateNums, itemWeights, itemVolumes = [[[] for _ in range(sizeNeeded)] for _ in range(3)]
>>> itemDateNums[1].append("hello world")
>>> itemDateNums
[[], ['hello world'], [], []]
>>> itemWeights
[[], [], [], []]
当然,这个更清洁是否是另一个问题。恕我直言,你应该把它分成三行。代码重复并不是那么糟糕,这样就可以立即清楚代码的作用。
答案 2 :(得分:0)
[[]] * sizeNeeded
存在对同一个内部元素进行多次引用的问题(无论您对相同的单个外部列表进行了多少次引用)。列表推导没有同样的问题:
itemDateNums = [ [] for i in range( sizeNeeded ) ]
itemWeights = [ [] for i in range( sizeNeeded ) ]
itemVolumes = [ [] for i in range( sizeNeeded ) ]
或者,冒着被混淆的风险,你可以在一个作业中做到:
itemDateNums, itemWeights, itemVolumes = zip( *[ ([],[],[]) for i in range( sizeNeeded ) ] )