Python yield(从 Ruby 迁移):如何编写一个没有参数的函数,只有 yield 来做打印?



我一直在将Ruby代码转换为Python代码,现在我坚持使用这个包含yield的函数:

def three_print():
yield
yield
yield

我想调用该函数并告诉它打印"Hello"三次,因为三个yield语句。由于该函数不接受任何参数,因此出现错误。你能告诉我让它工作的最简单方法吗?谢谢。

Ruby中的yield和Python中的yield是两个非常不同的东西。

在 Rubyyield中运行一个作为参数传递给函数的块。

红宝石:

def three
yield
yield
yield
end
three { puts 'hello '} # runs block (prints "hello") three times

在 Python 中,yield从生成器(这是一个使用yield的函数)抛出一个值并停止执行该函数。所以这是完全不同的东西,更有可能的是你想将函数作为参数传递给 Python 中的函数。

蟒:

def three(func):
func()
func()
func()
three(lambda: print('hello')) # runs function (prints "hello") three times

蟒蛇生成器

下面的代码(您提供的代码)是一个生成器,它返回None三次:

def three():
yield
yield
yield
g = three() #=> <generator object three at 0x7fa3e31cb0a0>
next(g) #=> None
next(g) #=> None
next(g) #=> None
next(g) #=> StopIteration

我能想象它如何用于打印"Hello"三次的唯一方法 - 将其用作迭代器:

for _ in three():
print('Hello')

红宝石类比

您可以使用Enumerator.new在 Ruby 中做类似的事情:

def three
Enumerator.new do |e|
e.yield # or e << nil
e.yield # or e << nil
e.yield # or e << nil
end
end
g = three
g.next #=> nil
g.next #=> nil
g.next #=> nil
g.next #=> StopIteration
three.each do
puts 'Hello'
end

Python 中的yield不像在 Ruby 中那样工作。特别是,这并不意味着"在此处执行块参数"。此函数永远不会执行回调。

在 Python 中,yield用于创建迭代器(特别是生成器),您发布的函数将返回一个产生 3 次None的迭代器。您可以遍历迭代器并为每个值打印"Hello",忽略None

for _ in three_print():
print("Hello")

这是最接近 Ruby 行为的,但在底层机制方面仍然有根本的不同。

或者,如果您确实想要一个将执行 3 次回调的函数,那就是

def f(callback):
callback()
callback()
callback()

你可以称之为

f(lambda: print("Hello"))

您可以使用:

def three_print():
yield"Hellon"*3
print(''.join(list(three_print())))
# Hello
# Hello
# Hello
def three_print():
yield("Hello")
yield("Hello")
yield("Hello")

由于有三个yields,你需要调用three_print().next()三次才能得到要输出的"Hello"字符串

您可以在循环中屈服:

def hello():
for i in range(3):
yield "hello"
print(list(hello()))

输出:

['hello', 'hello', 'hello']

在 Python3.3 及更高版本中,您可以使用yield from语句:

def hello():
yield from ["hello" for i in range(3)]
print(list(hello()))

输出:

['hello', 'hello', 'hello']

最新更新