在this Python documentation中,以下内容用作生成器表达式的示例:
dict((fn(i+1), code)
for i, code in enumerate('FGHJKMNQUVXZ')
for fn in (int, str))
>> {1: 'F', '1': 'F', 2: 'G', '2': 'G', 3: 'H', '3': 'H', 4: 'J',...}
我不明白第二个for
循环for fn in (int, str)
如何将int值转换为字符串并在字典中添加一个附加条目。
我找到了this Stack Overflow question,但在这种情况下,我仍无法知道第二个for
循环是如何工作的。
答案 0 :(得分:8)
它可能有助于#34;展开"生成器表达式中的循环,并将它们写为独立的for
循环。为此,您将所有for (variable) in (iterable)
语句放在不同的行中,按相同的顺序排列,但将事物从前面移动到最内层for循环的主体。像这样,一般来说:
thing for a in a_list for b in b_list for c in c_list
变为
for a in a_list:
for b in b_list:
for c in c_list:
thing
除了当你执行生成器表达式时,所有thing
自动进入列表或字典或其他任何内容。在你的情况下,
dict((fn(i+1), code)
for i, code in enumerate('FGHJKMNQUVXZ')
for fn in (int, str))
变为
for i, code in enumerate('FGHJKMNQUVXZ'):
for fn in (int, str):
(fn(i+1), code)
除了将所有元组转换为dict
。
正如其他答案所解释的那样,您可以跟踪这两个for
循环的执行情况。首先,外部循环将i
设置为0
并将code
设置为'F'
,并且在其中,内部循环将fn
设置为int
并且然后到str
,所以你得到
int(0+1, 'F')
str(0+1, 'F')
之后会转到下一个i
和code
。
答案 1 :(得分:4)
正如您所见,fn(i+1)
将被调用两次。第一个int(i+1)
,第二个str(i+1)
for a in ((fn(i+1), code)
for i, code in enumerate('FGH')
for fn in (int, str)):
print a
输出:
(1, 'F')
('1', 'F')
(2, 'G')
('2', 'G')
(3, 'H')
('3', 'H')
简化循环以提高可读性:
for i, code in enumerate('FGH'):
for fn in (int, str):
print i, code, fn
输出:
0 F <type 'int'>
0 F <type 'str'>
1 G <type 'int'>
1 G <type 'str'>
2 H <type 'int'>
2 H <type 'str'>
答案 2 :(得分:3)
原因是因为这个(fn(i+1), code))
生成器产生一个元组,第一个项目是int或string,第二个值是来自'FGHJKMNQUVXZ'
这是另一个没有第二个for循环的例子
def gen_func(text):
for i, code in enumerate(text):
yield i, code
yield str(i), code
print(dict(gen_func('FGHJKMNQUVXZ')))
for fn in (int, str)
发生的所有情况都是fn
可以是内置的int
或str
函数来转换i
的值。
int(i)
str(i)
答案 3 :(得分:2)
代码在Python类名中使用它,它也可以用来调用返回该类实例的构造函数。例如:
class A(object):
def __init__(value):
self.value = value
a = A(10)
请注意,A
既是类名,也可以用作Python callable
。这里的好处是int
和str
也可以同样的方式使用!
z = 10
value = int(z) # Returns number 10
print isinstance(value, int) # Prints True
print isinstance(value, str) # Prints False
value = str(z) # returns '10'
print isinstance(value, int) # Prints False
print isinstance(value, str) # Prints True
所以第二个循环使用str
和int
作为返回第一个for
循环中索引的字符串或整数表示的函数。你也可以想象写了两个这样的函数:
def as_int(value):
return int(value)
def as_str(value):
return str(value)
然后像这样编写for
循环:
dict((fn(i+1), code)
for i, code in enumerate('FGHJKMNQUVXZ')
for fn in (as_int, as_str))
# This second loop loops over the 2-element tuple
# whose contents are the two functions `as_int` and `as_str`
作为示例的长版本。
答案 4 :(得分:1)
在您的示例中,您正在使用由以下文字表示的元组的序列(此处由生成器表达式提供)构建字典
(fn(i+1), code)
在这个元组文字中,所有术语(1
:)除外都是由两个循环提供的;外循环
… for i, code in enumerate('TROIDSNB') …
为您提供i
,一个整数值和code
,一个1个字符的长字符串 - 执行内循环时这些值是固定的;
内部循环为您提供fn
… for fn in (int, str) …
可以假设2个值,fn=int
或fn=str
。
构建第一个元组时,i=0
,code='T'
和fn=int
(int(0+1), 'T')
构建第二个元组时,i
和code
(由外部循环提供)没有改变,只有fn=str
,所以新的元组,传递给字典构造函数,是
(str(0+1), 'T')
此时内部循环已到达终点...外部循环更新其变量i=1
和code=R
的值,内部循环被重置,因此fn=int
和生成新元组
(int(1+1), 'R')
等等