从Ruby移植到Python:如何处理'yield'



我目前尝试将一段代码从Ruby移植到Python,以进行一些算法研究。我没有 Ruby 的经验,不知道如何处理"yield"关键字。

该代码适用于迈尔斯差异算法,并在本博客中进行了全面描述

这是我不明白的代码片段:

while x > prev_x and y > prev_y
yield x - 1, y - 1, x, y
x, y = x - 1, y - 1
end

有没有办法在 Python 中近似这一点?

几乎相同。尽管 Python 和 Rubyyield的语义有些不同,但在这种情况下,它们几乎完全一致。

Ruby 的yield调用一个传递给函数的块,并为其提供参数。

Python 的yield使函数成为生成器,并从中生成一个输出。


它们都只在函数的上下文中有意义,因此只有您的while循环太短而无法使用它。但是,让我们在 Ruby 中以类似的东西作为简化的示例:

def numbers_and_doubles(n)
i = 0
while i < n
yield i, 2 * i
i += 1
end
end

此函数接受具有一个参数的块,然后生成最多为该数字的数字及其双精度数,并使用这些参数执行该块:

numbers_and_doubles(5) do |num, double|
puts "#{num} * 2 = #{double}"
end

由于块与回调函数基本相同,因此它相当于这个 Python:

def numbers_and_doubles(n, callback):
i = 0
while i < n:
callback(i, i*2)
i += 1
def output(num, double):
print(f"{num} * 2 = {double}")
numbers_and_doubles(5, output)

另一方面,Python 的yield创建了一个生成器 - 一个返回可以按需生成值的函数的函数:

def numbers_and_doubles(n):
i = 0
while i < n:
yield i, 2 * i
i += 1

使用生成器的最自然方法是通过for循环:

for num, double in numbers_and_doubles(5):
print(f"{num} * 2 = {double}")

在 Ruby 中,最接近的直译是Enumerator

def numbers_and_doubles(n)
Enumerator.new do |yielder|
i = 0
while i < n
yielder.yield(i, i*2)
i += 1
end
end
end

消费Enumerator最自然的方式是使用each(这是Rubyists更喜欢for):

numbers_and_doubles(5).each do |num, double|
puts "#{num} * 2 = #{double}"
end

但是,正如我所说,即使他们做了一些稍微不同的事情,上面的原始Ruby(带有yield)与上面的原始Python(带有yield)惊人地相似。它们的消费方式略有不同,但适合每种语言的习语。

在您的情况下,如果您yield完全保留在 Python 中,则使用它的行会从 Ruby 的

backtrack do |prev_x, prev_y, x, y|

到蟒蛇的

for prev_x, prev_y, x, y in backtrack():

您可以在Python yield vs Ruby yield中阅读更多内容。


请注意,编写此循环的最自然方法不是用任何一种语言while(我会在 Python 中使用range,在 Ruby 中使用times),但我希望两种语言的代码看起来相似,以便进行比较。

让我们看看博客中的代码:

def diff
diff = []
backtrack do |prev_x, prev_y, x, y|
a_line, b_line = @a[prev_x], @b[prev_y]
if x == prev_x
diff.unshift(Diff::Edit.new(:ins, nil, b_line))
elsif y == prev_y
diff.unshift(Diff::Edit.new(:del, a_line, nil))
else
diff.unshift(Diff::Edit.new(:eql, a_line, b_line))
end
end
diff
end

正如我们所看到的,块被传递给带有四个参数的backtrack方法,因此理论上在此方法的实现中,您必须向其传递一个回调函数。

最新更新