【问题标题】:Python: passing argument to generator object created by generator expression?Python:将参数传递给由生成器表达式创建的生成器对象?
【发布时间】:2019-08-10 09:10:18
【问题描述】:

所以我有这个 gen 对象:

yld123cu = (x * u for x in range(1, 4))

我只能这样使用:

u = 2  # some user given value
for i in yld123cu:
    print(i, end=' ')

是否有任何语法可以避免 u=.. 赋值的额外行? 有什么方法可以将 u 值放入 for 语句中?

我想要类似于下面的东西,但使用的是 gen 表达式,而不是函数:

def yld123u(u):
    for i in range(1, 4):
        yield i * u

for i in yld123u(2):
    print(i, end=' ')

【问题讨论】:

  • "id 想要类似于下面的东西,但使用的是 gen 表达式,而不是函数:" -- 为什么?这是一个完全有效且有效的解决方案。而在幕后两者之间或多或少没有区别
  • 谢谢大家的每一个回复!今天从他们每个人身上学到了一些东西。真的很感激,很棒的网站))

标签: python python-3.x


【解决方案1】:

由于生成器表达式不能有自己的范围,因此首选方法是按照您的建议定义生成器函数。

def yld123u(u):
    for i in range(1, 4):
        yield i * u

如果您需要在此过程中更新u,这就是您想要避免上述情况的原因,那么请知道您可以将send 值传递给生成器。

def yld123u(u):
    for i in range(1, 4):
        received = yield i * u # a sent value will be assigned to 'received'
        u = u if received is None else received

示例

如果您不使用 send,生成器的行为仍然相同。

for x in yld123u(4):
    print(x)

输出

4
8
12 

您可以使用send 来更新u 的值。

gen = yld123u(4)
v0 = next(gen)
v1 = gen.send(0)
v2 = gen.send(4)
print(v0, v1, v2)

输出

4 0 12

输入循环

如果您需要生成器与用户输入进行交互,这是我过去的答案,它建议了一种实现 yield-receive generator usable in a for-loop 的方法。

class YieldReceive:
    stop_iteration = object()

    def __init__(self, gen):
        self.gen = gen
        self.next = next(gen, self.stop_iteration)

    def __iter__(self):
        return self

    def __next__(self):
        if self.next is self.stop_iteration:
            raise StopIteration
        else:
            return self.next

    def send(self, value):
        try:
            self.next = self.gen.send(value)
        except StopIteration:
            self.next = self.stop_iteration

用法

it = YieldReceive(yld123u(4))
for x in it:
    print(x)
    it.send(int(input('Enter next u value: ')))

【讨论】:

  • 嘿,Olivier,非常感谢您提供出色的洞察力和详细信息!以及发送方法的链接。我整天都在玩 pycharm 调试器。所以 gen 函数 + send/next 是要走的路,好吧。我在 c-family 之后几周才开始学习 python,昨天刚到 oop 部分,所以我也很喜欢逐步完成你的课堂示例。你所做的如此崇高的工作如此慷慨地帮助人们,祝你一切顺利!
【解决方案2】:

您可以使用lambda。这对我有用:

yld123cu = lambda u: (x * u for x in range(1, 4))

for i in yld123cu(2):
    print(i, end=' ')

【讨论】:

  • 谢谢 Uli,但这仍然使它成为一个函数。我更感兴趣的是让它成为一个生成器对象,并且仍然能够使用一些类似函数调用的语法将参数传递给它
  • 一个命名的 lambda 被认为是bad practice by PEP8
  • 感谢@OlivierMelançon 的提示。 +1
【解决方案3】:

你可以这样试试。

注意:在这里,我们没有使用命名 lambda 函数的问题。

for i in (lambda u: (x * u for x in range(1, 4)))(u=2): 
    print(i, end=' ')

for i in (lambda u: (x * u for x in range(1, 4)))(2): 
    print(i, end=' ')

» 输出

2 4 6 

【讨论】:

    猜你喜欢
    • 2014-06-25
    • 2019-11-24
    • 2016-08-14
    • 2017-05-07
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 2017-12-08
    • 2014-09-23
    相关资源
    最近更新 更多