这里到底发生了什么? (Python 3.7.6)
What exactly is going on here? (Python 3.7.6)
我正在研究别人在 Codewars 上的解决方案,对某些事情有点困惑。这是原始问题的 link:Reverse or Rotate?。感谢原作者 falsetru.
解决方法如下:
def revrot(strng, sz):
return ''.join(
chunk[1:] + chunk[:1] if sum(int(d)**3 for d in chunk) % 2 else chunk[::-1]
for chunk in map(''.join, zip(*[iter(strng)]*sz))
)
我想我明白了大部分。除了这部分:
zip(*[iter(strng)]*sz)
我认为以这种方式使用的 * 表示一个非关键字可变长度参数列表 - 这意味着可以有任意数量的原始字符串 (strng
),它们的长度sz
,例如 6。根据文档,zip()
函数正在接收一些可变数量的可迭代对象,这是它所需要的。 (对吗?)
那么,map(''.join, zip(*[iter(strng)]*sz)
首先 returns 字符串 strng
的迭代器。它returns this 在一个列表里面。似乎该列表随后乘以 sz
(为什么?)。它 returns 压缩了可变数量的结果(因此 *
)。 zip()
returns 一个元组(我猜?),然后通过 map
.
通过 join
函数传递
问题:
- 这是否接近正确?
- 为什么 iter(strng) 必须放在列表中
[]
?
- 为什么可以加入
zip
的结果?我尝试加入 ('m',)
作为测试并获得了 'm'
。对为什么这也有效感到困惑。
- 有人可以解释一下 * 吗?我对什么时候应该使用它感到困惑...
谢谢。我仍然是 Python 的初学者,所以非常感谢您的帮助! (即使只是我的一个问题!)
要了解发生了什么,我们要分析语句
for chunk in map(''.join, zip(*[iter(strng)]*sz))
由内而外:
iter(strng)
returns 每次使用 next
或在循环中访问的迭代器 consumes strng
的一个元素(一个字符)和returns表示的元素。
[iter(strng)]
是一个列表,它的唯一元素是迭代器
[iter(strng)]*sz
是 sz
个列表副本的串联,[iter(strng), ..., iter(strng)]
包含 sz
次 相同的迭代器对象,我的意思是字面上相同的迭代器对象.
*[iter(strng)]*sz
等同于 *[iter(strng), ..., iter(strng)]
并且,当在函数参数列表中使用时,解压 其内容:函数将其参数列表视为(iter(strng), ..., iter(strng))
.
zip(*[iter(strng)]*sz)
因此等同于 zip(iter(strng), ..., iter(strng))
.
- 在每次迭代中,
zip
获取其每个参数的第一个元素并将它们放入一个元组中,但是因为对 iter
的各种引用都引用相同的原始实例 iter(strng)
zip
返回的第一个元组包含 strng
的前 sz
个字符,第二个包含 sz+1
到 2*sz
个字符等
- 最后,每个元组都是
''.join()
的参数,所以我们有一系列字符串,每个长 sz
个字符,跨越原始 strng
.
就是这样。
我正在研究别人在 Codewars 上的解决方案,对某些事情有点困惑。这是原始问题的 link:Reverse or Rotate?。感谢原作者 falsetru.
解决方法如下:
def revrot(strng, sz):
return ''.join(
chunk[1:] + chunk[:1] if sum(int(d)**3 for d in chunk) % 2 else chunk[::-1]
for chunk in map(''.join, zip(*[iter(strng)]*sz))
)
我想我明白了大部分。除了这部分:
zip(*[iter(strng)]*sz)
我认为以这种方式使用的 * 表示一个非关键字可变长度参数列表 - 这意味着可以有任意数量的原始字符串 (strng
),它们的长度sz
,例如 6。根据文档,zip()
函数正在接收一些可变数量的可迭代对象,这是它所需要的。 (对吗?)
那么,map(''.join, zip(*[iter(strng)]*sz)
首先 returns 字符串 strng
的迭代器。它returns this 在一个列表里面。似乎该列表随后乘以 sz
(为什么?)。它 returns 压缩了可变数量的结果(因此 *
)。 zip()
returns 一个元组(我猜?),然后通过 map
.
join
函数传递
问题:
- 这是否接近正确?
- 为什么 iter(strng) 必须放在列表中
[]
? - 为什么可以加入
zip
的结果?我尝试加入('m',)
作为测试并获得了'm'
。对为什么这也有效感到困惑。 - 有人可以解释一下 * 吗?我对什么时候应该使用它感到困惑...
谢谢。我仍然是 Python 的初学者,所以非常感谢您的帮助! (即使只是我的一个问题!)
要了解发生了什么,我们要分析语句
for chunk in map(''.join, zip(*[iter(strng)]*sz))
由内而外:
iter(strng)
returns 每次使用next
或在循环中访问的迭代器 consumesstrng
的一个元素(一个字符)和returns表示的元素。[iter(strng)]
是一个列表,它的唯一元素是迭代器[iter(strng)]*sz
是sz
个列表副本的串联,[iter(strng), ..., iter(strng)]
包含sz
次 相同的迭代器对象,我的意思是字面上相同的迭代器对象.*[iter(strng)]*sz
等同于*[iter(strng), ..., iter(strng)]
并且,当在函数参数列表中使用时,解压 其内容:函数将其参数列表视为(iter(strng), ..., iter(strng))
.zip(*[iter(strng)]*sz)
因此等同于zip(iter(strng), ..., iter(strng))
.- 在每次迭代中,
zip
获取其每个参数的第一个元素并将它们放入一个元组中,但是因为对iter
的各种引用都引用相同的原始实例iter(strng)
zip
返回的第一个元组包含strng
的前sz
个字符,第二个包含sz+1
到2*sz
个字符等 - 最后,每个元组都是
''.join()
的参数,所以我们有一系列字符串,每个长sz
个字符,跨越原始strng
.
就是这样。