为什么使用索引号进行迭代时Python的工作方式有所不同?例如,对于zip函数(在for循环中使用时没有索引),值不会存储在变量中。使用enumerate()函数(允许我在foor循环中使用“索引”)时,它通常会发生。
当我尝试在循环内外打印它时,不使用索引的解决方案的“ width”变量具有不同的值,这里的zip()函数用于处理列表中的两个列表。同时无需处理其索引:
tableData = [['apples', 'oranges', 'cherries', 'banana'],
['Alice', 'Bob', 'Carol', 'David'],
['dogs', 'cats', 'moose', 'goose']]
def printTable(myListOfLists):
colWidths = [0] * len(myListOfLists)
for lists, width in zip(myListOfLists, colWidths):
for item in lists:
if width < len(item):
width = len(item)
print(width) #This prints my 'width' rightly
print(colWidths) #This prints my 'width' wrongly
printTable(tableData)
上面的代码产生以下不需要的输出:
8
5
5
[0, 0, 0]
但是,如果我使用enumerate()(生成索引以同时使用两个列表),则在for循环中修改的值将正确保存在width变量中,请参见代码示例:
tableData = [['apples', 'oranges', 'cherries', 'banana'],
['Alice', 'Bob', 'Carol', 'David'],
['dogs', 'cats', 'moose', 'goose']]
def printTable(myListOfLists):
colWidths = [0] * len(myListOfLists)
for index, lists in enumerate(myListOfLists):
for item in lists:
if colWidths[index] < len(item):
colWidths[index] = len(item)
print(colWidths[index]) #This prints my 'width' rightly
print(colWidths) #This ALSO prints my 'width' rightly
printTable(tableData)
第二个输出是:
8
5
5
[8, 5, 5]
然后,请问如何使用zip()并修改我的“外部”变量?我究竟做错了什么?谢谢。
答案 0 :(得分:2)
我相信,您想要实现的是从tableData
获取给定子列表中最长项目的长度。为此,您可以从子列表中获取最长的字符串,然后像这样测量其长度:
tableData = [['apples', 'oranges', 'cherries', 'banana'],
['Alice', 'Bob', 'Carol', 'David'],
['dogs', 'cats', 'moose', 'goose']]
def printTable(myListOfLists):
colWidths = []
for sub_list in myListOfLists:
longest_item = max(sub_list, key=len)
colWidths.append(len(longest_item))
print(colWidths)
printTable(tableData)
编辑并说明:
通过使用for lists, width in zip(myListOfLists, colWidths):
在每个周期中
1)单个列表,其中tableData中的字符串为lists
。
2)整数,与colWidths一样,精确为0,width
然后,在对每个文本(如“苹果”,“橙子”等)进行迭代时。
您在这里做什么:
width = len(item)
就像是说“现在宽度不再是0,它是len(item)
,这样您就不会影响列表colWidths
,因为您没有使用它,而是在进行操作此0
值,与colWidths
列表中的位置无关,它只是0,被“宽度”名称下的len(item)
替换。
答案 1 :(得分:1)
这样,您将不会更改列表的值,而需要索引来更改实际值。
示例:
for e in [1, 2, 3]:
e = 10 # this way is wrong
data = [1, 2, 3]
for index, e in enumerate(data):
e[index] = 50 # always it is needed an index
解决问题的好方法:
tableData = [['apples', 'oranges', 'cherries', 'banana'],
['Alice', 'Bob', 'Carol', 'David'],
['dogs', 'cats', 'moose', 'goose']]
data = [len(max(e, key=len)) for e in tableData]
print(data)
或
tableData = [['apples', 'oranges', 'cherries', 'banana'],
['Alice', 'Bob', 'Carol', 'David'],
['dogs', 'cats', 'moose', 'goose']]
def printTable(myListOfLists):
colWidths = [0] * len(myListOfLists)
for index, row in enumerate(myListOfLists):
colWidths[index] = len(max(row, key=len))
print(colWidths)
printTable(tableData)
另一方面,您可以尝试一下。
for i, (a, b) in enumerate(zip(alist, blist)):
print i, a, b
答案 2 :(得分:1)
enumerate
是一种生成索引的Python方法(类似于for i in range(len(...):
colWidths = [0] * len(myListOfLists)
for index, lists in enumerate(myListOfLists):
for item in lists:
if colWidths[index] < len(item):
colWidths[index] = len(item)
这里lists
和item
来自myListOfLists
,但是您明确修改了colWidths
列表。
在第一种情况下,您正在修改一个迭代变量,而不是源列表:
colWidths = [0] * len(myListOfLists)
for lists, width in zip(myListOfLists, colWidths):
for item in lists:
if width < len(item):
width = len(item)
width
是一个迭代变量。但是width = len(item)
行为变量(名称)分配了一个新值,从而中断了它与源数组的链接。在下一次迭代中,width
再次由迭代器设置。源列表colWidths
不变。
此模式适用于简单情况:
alist = [1,2,3,4]
for i in alist:
i = 5 # does nothing to alist
for i in range(4):
alist[i] = 5 # changes an element of alist
对迭代变量的更改非常棘手。您必须了解它何时表示“可变”,而不是。并且了解分配给变量和修改对象(如列表)之间的区别。