Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/313.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_Variables_Generator_Local - Fatal编程技术网

Python 将局部变量添加到正在运行的生成器

Python 将局部变量添加到正在运行的生成器,python,variables,generator,local,Python,Variables,Generator,Local,最近,我尝试从运行的生成器外部设置局部变量。生成器代码也应该访问这些变量 一个问题是,当访问变量时,解释程序认为它必须是全局变量,因为变量没有设置在局部范围内。但是我不想改变全局变量,也不想复制整个全局范围来人为地使变量局部化 另一个问题是,当从外部访问时,本地(和全球?)词典被绑定为只读 是否有任何合法(或至少部分合法)的方式将局部变量引入正在运行的生成器实例 编辑以澄清: 我不是说“发送”功能。这当然是一个简洁的函数,但由于我想用不同的名称设置多个变量,因此对我来说并不方便。locals()

最近,我尝试从运行的生成器外部设置局部变量。生成器代码也应该访问这些变量

一个问题是,当访问变量时,解释程序认为它必须是全局变量,因为变量没有设置在局部范围内。但是我不想改变全局变量,也不想复制整个全局范围来人为地使变量局部化

另一个问题是,当从外部访问时,本地(和全球?)词典被绑定为只读

是否有任何合法(或至少部分合法)的方式将局部变量引入正在运行的生成器实例

编辑以澄清:

我不是说“发送”功能。这当然是一个简洁的函数,但由于我想用不同的名称设置多个变量,因此对我来说并不方便。

locals()始终返回只读dict。您可以创建自己的“locals”字典:

def gen_func():
    lcls = {}
    for i in range(5):
        yield (i, lcls)
        print lcls


for (val, lcls) in gen_func():
    lcls[val] = val
任何其他可变结构也可以使用。

locals()始终返回只读dict。您可以创建自己的“locals”字典:

def gen_func():
    lcls = {}
    for i in range(5):
        yield (i, lcls)
        print lcls


for (val, lcls) in gen_func():
    lcls[val] = val

任何其他可变结构也可以工作。

您可能正在寻找的是允许将值发送到生成器的方法。提供了一个示例:

>>> def echo(value=None):
...     print "Execution starts when 'next()' is called for the first time."
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception, e:
...                 value = e
...     finally:
...         print "Don't forget to clean up when 'close()' is called."
...
>>> generator = echo(1)
>>> print generator.next()
Execution starts when 'next()' is called for the first time.
1
>>> print generator.next()
None
>>> print generator.send(2)
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.

让我举一个我自己的例子(注意!上面的代码是Python 2.6,但下面我将编写Python 3;)

>>> def amplify(iter, amp=1):
...     for i in iter:
...         reply = (yield i * amp)
...         amp = reply if reply != None else amp 
... 
>>> it = amplify(range(10))
>>> next(it)
0
>>> next(it)
1
>>> it.send(3) # 2 * 3 = 6
6
>>> it.send(8) # 3 * 8 = 24
24
>>> next(it) # 4 * 8 = 32
32
当然,如果您真的愿意,您也可以在不发送
的情况下执行此操作。例如,通过将生成器封装在一个类中(但它没有那么优雅!):


更新:好的,既然你已经更新了你的问题,让我再尝试一下这个问题。也许这就是你的意思

>>> def amplify(iter, loc={}):
...     for i in iter:
...         yield i * loc.get('amp', 1)
... 
>>> it = amplify(range(10), locals())
>>> next(it)
0
>>> next(it)
1
>>> amp = 3
>>> next(it)
6
>>> amp = 8
>>> next(it)
24
>>> next(it)
32

请注意,应该将其视为只读,并且与范围相关。如您所见,您需要显式地将
locals()
传递给生成器。我看没有办法解决这个问题……

您可能正在寻找的是允许将值发送到生成器的方法。提供了一个示例:

>>> def echo(value=None):
...     print "Execution starts when 'next()' is called for the first time."
...     try:
...         while True:
...             try:
...                 value = (yield value)
...             except Exception, e:
...                 value = e
...     finally:
...         print "Don't forget to clean up when 'close()' is called."
...
>>> generator = echo(1)
>>> print generator.next()
Execution starts when 'next()' is called for the first time.
1
>>> print generator.next()
None
>>> print generator.send(2)
2
>>> generator.throw(TypeError, "spam")
TypeError('spam',)
>>> generator.close()
Don't forget to clean up when 'close()' is called.

让我举一个我自己的例子(注意!上面的代码是Python 2.6,但下面我将编写Python 3;)

>>> def amplify(iter, amp=1):
...     for i in iter:
...         reply = (yield i * amp)
...         amp = reply if reply != None else amp 
... 
>>> it = amplify(range(10))
>>> next(it)
0
>>> next(it)
1
>>> it.send(3) # 2 * 3 = 6
6
>>> it.send(8) # 3 * 8 = 24
24
>>> next(it) # 4 * 8 = 32
32
当然,如果您真的愿意,您也可以在不发送
的情况下执行此操作。例如,通过将生成器封装在一个类中(但它没有那么优雅!):


更新:好的,既然你已经更新了你的问题,让我再尝试一下这个问题。也许这就是你的意思

>>> def amplify(iter, loc={}):
...     for i in iter:
...         yield i * loc.get('amp', 1)
... 
>>> it = amplify(range(10), locals())
>>> next(it)
0
>>> next(it)
1
>>> amp = 3
>>> next(it)
6
>>> amp = 8
>>> next(it)
24
>>> next(it)
32

请注意,应该将其视为只读,并且与范围相关。如您所见,您需要显式地将
locals()
传递给生成器。我看没有办法解决这个问题…

如果您想要一个同时充当接收器的协程或生成器,您应该使用send方法,如中所示。如果要通过设置生成器中的各种属性来更改运行时行为,有一个由Raymond Hettinger编写的旧版本:

def foo_iter(self):
    self.v = "foo"
    while True:
        yield self.v

enableAttributes(foo_iter)
it = foo_iter()
print it.next()
it.v = "boo"
print it.next()
这将打印:

foo
boo

enableAttributes
函数转换为适当的修饰符应该不会太困难

如果您希望有一个同时充当接收器的协程或生成器,则应使用send方法,如中所示。如果要通过设置生成器中的各种属性来更改运行时行为,有一个由Raymond Hettinger编写的旧版本:

def foo_iter(self):
    self.v = "foo"
    while True:
        yield self.v

enableAttributes(foo_iter)
it = foo_iter()
print it.next()
it.v = "boo"
print it.next()
这将打印:

foo
boo

enableAttributes
函数转换为适当的修饰符应该不会太困难

谢谢你提供了很长的例子。在我的问题的第一次编辑中,我忘了在这里添加关于“发送”的注释。好的,我现在添加了另一个版本,带有
locals()
。也许这适合你的需要?谢谢你提供了很长的例子。在我的问题的第一次编辑中,我忘了在这里添加关于“发送”的注释。好的,我现在添加了另一个版本,带有
locals()
。也许这适合你的需要?嗨,托斯滕,谢谢,这真的很接近我想要做的。我不知道那个食谱,它对我来说真的很有趣(必须在一个安静的小时内仔细检查)。不过,在生成器编码中有一些更方便的东西还是不错的……嗨,托尔斯滕,谢谢,这真的很接近我想要做的。我不知道那个食谱,它对我来说真的很有趣(必须在一个安静的小时内仔细检查)。不过,在生成器编码中有一些更方便的东西还是不错的。。。