如何乘以列表并设置单个变量?
How to multiply lists and set a single variable?
我正在尝试创建一个长列表,而不必每次都手动输入。我目前正在使用它(为简单起见,将较长的数字替换为 0):
mylist = [[0]*5]*5
即:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
打印每一行,此列表如下所示:
00000
00000
00000
00000
00000
当我尝试更改其中一个数字(比方说第一行和第一项)时,它会设置所有行的第一项。
mylist[0][0] = 1
打印每一行:
10000
10000
10000
10000
10000
如何设置只我想要的项目?
您看到此行为是因为您创建了一个列表 mylst
,其中包含 相同 列表的五个副本。
您可以使用 id
来查看,其中 returns 对象的唯一标识符:
In [1]: lst = [[0]*5]*5
In [2]: [id(sublst) for sublst in lst]
Out[2]:
[139951176432584,
139951176432584,
139951176432584,
139951176432584,
139951176432584]
这是因为 [0]*5
为您提供了一个包含五个零的列表,但是将其乘以 5 会为您提供同一列表的五个副本,而不是五个具有相同值的不同列表。
您可以通过使用列表理解来初始化原始列表来避免此行为:
In [3]: lst = [[0]*5 for _ in range(5)]
In [4]: [id(sublst) for sublst in lst]
Out[4]:
[139951176420808,
139951176419528,
139951176419464,
139951176419592,
139951176324040]
就风格而言,我更愿意避免使用 *
来创建简单的平面列表以外的任何内容。那么,为了保持一致性,我最初可能会创建您的列表:
In [3]: lst = [[0 for _ in range(5)] for _ in range(5)]
这种方法的优点是,如果以后您想要将值初始化为自定义对象(例如,Banana()
,而不是 0
,则无需更改任何内容).
如果没有这种方法,您可以 运行 进入与以前相同的问题,只是现在将重复内部列表中的 object:
In [5]: class Banana(object):
...: pass
...:
In [6]: lst = [[Banana()]*5 for _ in range(5)]
In [7]: [[id(elem) for elem in sublst] for sublst in lst]
Out[7]:
[[139951176414824,
139951176414824,
139951176414824,
139951176414824,
139951176414824],
[139951176415272,
139951176415272,
139951176415272,
139951176415272,
139951176415272],
[139951176414096,
139951176414096,
139951176414096,
139951176414096,
139951176414096],
[139951176414432,
139951176414432,
139951176414432,
139951176414432,
139951176414432],
[139951176415496,
139951176415496,
139951176415496,
139951176415496,
139951176415496]]
换句话说,0
在平面列表或其他地方起作用的唯一原因是拥有同一个 int
对象的多个副本(以及与其他内置类型(例如 float
),因为这些对象被视为不可变的并按值进行比较。
您不应该使用 * 运算符来构造列表,它会将相同的项目设置为所有列表。
使用
mylist = [[0 for n in range(5)] for _ in range(5)]
mylist[0][0] = 1
print(mylist)
输出:
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
我正在尝试创建一个长列表,而不必每次都手动输入。我目前正在使用它(为简单起见,将较长的数字替换为 0):
mylist = [[0]*5]*5
即:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
打印每一行,此列表如下所示:
00000
00000
00000
00000
00000
当我尝试更改其中一个数字(比方说第一行和第一项)时,它会设置所有行的第一项。
mylist[0][0] = 1
打印每一行:
10000
10000
10000
10000
10000
如何设置只我想要的项目?
您看到此行为是因为您创建了一个列表 mylst
,其中包含 相同 列表的五个副本。
您可以使用 id
来查看,其中 returns 对象的唯一标识符:
In [1]: lst = [[0]*5]*5
In [2]: [id(sublst) for sublst in lst]
Out[2]:
[139951176432584,
139951176432584,
139951176432584,
139951176432584,
139951176432584]
这是因为 [0]*5
为您提供了一个包含五个零的列表,但是将其乘以 5 会为您提供同一列表的五个副本,而不是五个具有相同值的不同列表。
您可以通过使用列表理解来初始化原始列表来避免此行为:
In [3]: lst = [[0]*5 for _ in range(5)]
In [4]: [id(sublst) for sublst in lst]
Out[4]:
[139951176420808,
139951176419528,
139951176419464,
139951176419592,
139951176324040]
就风格而言,我更愿意避免使用 *
来创建简单的平面列表以外的任何内容。那么,为了保持一致性,我最初可能会创建您的列表:
In [3]: lst = [[0 for _ in range(5)] for _ in range(5)]
这种方法的优点是,如果以后您想要将值初始化为自定义对象(例如,Banana()
,而不是 0
,则无需更改任何内容).
如果没有这种方法,您可以 运行 进入与以前相同的问题,只是现在将重复内部列表中的 object:
In [5]: class Banana(object):
...: pass
...:
In [6]: lst = [[Banana()]*5 for _ in range(5)]
In [7]: [[id(elem) for elem in sublst] for sublst in lst]
Out[7]:
[[139951176414824,
139951176414824,
139951176414824,
139951176414824,
139951176414824],
[139951176415272,
139951176415272,
139951176415272,
139951176415272,
139951176415272],
[139951176414096,
139951176414096,
139951176414096,
139951176414096,
139951176414096],
[139951176414432,
139951176414432,
139951176414432,
139951176414432,
139951176414432],
[139951176415496,
139951176415496,
139951176415496,
139951176415496,
139951176415496]]
换句话说,0
在平面列表或其他地方起作用的唯一原因是拥有同一个 int
对象的多个副本(以及与其他内置类型(例如 float
),因为这些对象被视为不可变的并按值进行比较。
您不应该使用 * 运算符来构造列表,它会将相同的项目设置为所有列表。
使用
mylist = [[0 for n in range(5)] for _ in range(5)]
mylist[0][0] = 1
print(mylist)
输出:
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]