Python关闭,局部变量范围错误 [英] Python closure, local variable scope error
问题描述
我的函数在赋值之前引用了局部变量'pt'抛出了我错误:
My function throw me with the local variable 'pt' referenced before assignment
error:
Traceback (most recent call last):
File "/home/solesschong/Workspace/PenPal/python/main.py", line 126, in callback
ind = (i+pt) % n
UnboundLocalError: local variable 'pt' referenced before assignment
代码为
def get_audio_callback(pt):
def callback(in_data, frame_count, time_info, status):
for i in range(frame_count):
ind = (i+pt) % n
return (a, b)
return callback
在全球范围内
pt = 0
stream = p.open(stream_callback=get_audio_callback(pt))
我无法弄清楚为什么会发生错误,因为我已经检查了一些关闭示例,没有发现任何区别。
I cannot figure out why the error occurs, since I've checked with some examples on closure and find no difference.
您无法重现错误的原因可能是由于过分简化,如@Martijn Pieters所述。
因此是原始代码。
The reason why you cannot reproduce the error might because of the over-simplify, as mentioned by @Martijn Pieters. Hence the original code.
我已经通过引用传递解决了这个问题,请看到我自己的答案。
Further I've solved this problem by passing by reference, plz see my own answer.
"""
Sound API
"""
def get_audio_callback(pt):
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+pt) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
pt = pt + frame_count
return (encode(wave), pyaudio.paContinue)
return callback
p = pyaudio.PyAudio()
pt = 0
stream = p.open(format=pyaudio.paFloat32,
channels=2,
rate=RATE,
output=True,
stream_callback=get_audio_callback(pt))
推荐答案
您的代码在回调
中分配给 pt
; Python在编译时确定名称范围,赋值使其成为本地名称。
Your code assigns to pt
in callback
; Python determines the scope of a name at compile time and assignment makes this a local name.
pt = pt + frame_count
除非您另行告诉Python,否则。在Python 2中,您只能将名称明确标记为 global
,而您需要Python 3才能使用 nonlocal
关键字:
Unless you tell Python otherwise, that is. In Python 2, you can only mark a name explicitly as a global
instead, you need Python 3 to be able to use the nonlocal
keyword:
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
nonlocal pt
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+pt) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
pt = pt + frame_count
return (encode(wave), pyaudio.paContinue)
使用 nonlocal pt
行明确告诉Python不要将 pt
当作本地名称,而应从 get_audio_callback
With the nonlocal pt
line Python is explicitly told not to treat pt
as a local name but to take it from the enclosing scope of get_audio_callback
instead.
在Python 2中,您只需创建一个位置从封包中获取值的al:
In Python 2, you can just create a local that takes its value from the closure:
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
pt_local = pt
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+pt_local) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
pt_local = pt_local + frame_count
return (encode(wave), pyaudio.paContinue)
因为您随附的 get_audio_callback
范围似乎未使用 pt
并且不需要访问更新的 pt_local
值。
because your enclosing get_audio_callback
scope doesn't appear to use pt
anyway and won't need access to the updated pt_local
value.
如果确实需要 pt
来更新 get_audio_callback
范围(例如,多次调用 callback
并且您需要 pt
从一个呼叫到另一个更新),您需要避免在该区域内部使用 pt
作为本地对象回调
函数。
If you do need pt
to update at the get_audio_callback
scope (if, say, callback
is called multiple times and you need pt
to be updated from call to call), you need to avoid using pt
as a local inside the callback
function altogether.
一种有效的解决方法是将值包装在可变对象中或赋值它是一个可变的属性,封闭范围和本地范围都可以在不被视为本地分配的情况下访问它。在回调
函数上设置属性是实现此目的的一种好方法:
One effective work-around for that is to wrap the value in a mutable object or assign it as a mutable attribute somewhere that both the enclosing scope and the local scope can access it without it ever being seen as a local assignment. Setting an attribute on the callback
function is a good way to do that:
def get_audio_callback(pt):
def callback(in_data, frame_count, time_info, status):
"""
This is the callback function for sound API
In each call, synthesized data is dumpped into the sound buffer
"""
wave = np.ndarray((frame_count, 2))
for i in range(frame_count):
ind = (i+callback.pt) % n
wave[i,0] = float(x[ind]) * 2
wave[i,1] = float(y[ind]) * 2
callback.pt = callback.pt + frame_count
return (encode(wave), pyaudio.paContinue)
callback.pt = pt
return callback
此处回调。 pt
不再是本地名称;它是回调
函数对象上的一个属性。
Here callback.pt
is no longer a local name; it is an attribute on the callback
function object instead.
这篇关于Python关闭,局部变量范围错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!