Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python生成器如何知道谁';他在打电话吗?_Python_Generator - Fatal编程技术网

Python生成器如何知道谁';他在打电话吗?

Python生成器如何知道谁';他在打电话吗?,python,generator,Python,Generator,这个问题让我毛骨悚然 如果我这样做: def mygen(): for i in range(100): yield i 从1000个线程调用它,生成器如何知道每个线程下一步要发送什么? 每次我调用它时,生成器是否会保存一个带有计数器和调用方引用的表或类似的内容 真奇怪 请澄清我的想法。这样的函数在调用时将返回生成器对象。如果在同一个生成器对象上有单独的线程调用next(),它们将相互干扰。也就是说,5个线程调用next()10次将获得50种不同的收益 如果两个线程各自

这个问题让我毛骨悚然

如果我这样做:

def mygen():
    for i in range(100):
        yield i
从1000个线程调用它,生成器如何知道每个线程下一步要发送什么? 每次我调用它时,生成器是否会保存一个带有计数器和调用方引用的表或类似的内容

真奇怪


请澄清我的想法。

这样的函数在调用时将返回生成器对象。如果在同一个生成器对象上有单独的线程调用
next()
,它们将相互干扰。也就是说,5个线程调用
next()
10次将获得50种不同的收益

如果两个线程各自通过在线程内调用
mygen()
来创建生成器,则它们将具有单独的生成器对象

生成器是一个对象,其状态将存储在内存中,因此每个创建
mygen()
的两个线程将引用单独的对象。这与从
类创建对象的两个线程没有什么不同,它们都有不同的对象,即使类是相同的


如果您是从C语言背景中得出这个结论的,那么这与使用
静态变量的函数是不同的。状态保存在对象中,而不是静态地保存在函数中包含的变量中。

mygen
不需要记住任何东西。每次调用
mygen()
都会返回一个独立的iterable。另一方面,这些iterables具有状态:每次对一个调用
next()
,它都会跳转到生成器代码中的正确位置——当遇到
yield
时,控制权就会交还给调用者。实际实现相当混乱,但原则上您可以想象这样的迭代器存储本地变量、字节码和字节码中的当前位置(也称为指令指针)。这里的线程没有什么特别之处。

如果您这样看,可能会更清楚。而不是:

for i in mygen():
    . . .
使用:

然后您可以看到mygen()只被调用一次,它创建了一个新的对象,正是这个对象被迭代。如果需要,可以在同一线程中创建两个序列:

gen1 = mygen()
gen2 = mygen()
print(gen1.__next__(), gen2.__next__(), gen1.__next__(), gen2.__next__())
这将打印0、0、1、1

如果愿意,您可以从两个线程访问同一迭代器,只需将generator对象存储在全局

global_gen = mygen()
线程1:

for i in global_gen:
    . . .
线程2:

for i in global_gen:
    . . .

这可能会造成各种破坏。:-)

你没有完全回答我的问题。我不想知道会发生什么,但想知道它是如何发生的。当线程创建生成器时,生成器是否会在内存中保留一些值?@patrickbasut生成器对象的状态与任何其他对象一样,因此是的,其状态将存储在内存中。是的,线程只是为了说明问题。考虑到生成器可能会给python初学者带来错误的并发外观(或比这更神奇的东西)。@Patrickbasut:好吧,你可以用它们进行模拟,也可以用协同程序进行模拟。生成器有点奇怪。您可以将它们分配给变量,但在您实际使用它们时,它开始以某种“按需”方式生成值。如果你指定了一个函数的内存位置,那就很容易理解了。但据我所知,您并没有这样做(实际上是在gen_obj=mygen()中调用函数)。哇!当您升级到下一个级别时,您可以将指向绑定的uuu next_uuu()方法的指针作为GUI回调传递给用户。:-)大多数情况下,“def”语句会从代码中创建一个函数对象,当您按名称调用函数时会执行该对象。但是,如果代码包含“yield”,def将创建两个函数对象:当调用函数名时被调用的函数对象根本没有代码;它只返回生成器对象。它从代码中创建的函数对象将通过该生成器对象的下一个属性调用,该函数将其状态保留在生成器对象中,并且知道如何在调用之间保存和还原它。感谢您的完整解释。我现在明白了(尽管还有一些问题超出了问题的范围)。谢谢
for i in global_gen:
    . . .