我有一个脚本创建一堆线程,运行程序使用线程从队列中运行任务,并从每个线程返回一些东西.我想计算其中有多少成功返回,所以我设置一个变量"successful = 0"并在每次队列报告任务成功完成时递增它.
但是,我得到"UnboundLocalError:局部变量'成功'在分配之前被引用"
这是怎么回事?
这是一些示例代码:
successful = 0
q = Queue(200)
for i in range(100):
t=Thread(target=foo)
t.daemon=True
t.start()
def foo():
while True:
task=q.get()
#do some work
print task
successful+=1 # triggers an error
q.task_done()
for i in range(100):
q.put("Foo")
q.join()
print successful
Run Code Online (Sandbox Code Playgroud) cache = {}
def func():
cache['foo'] = 'bar'
print cache['foo']
Run Code Online (Sandbox Code Playgroud)
产量
bar
Run Code Online (Sandbox Code Playgroud)
为什么这样做以及为什么不需要使用global关键字?
def do_something():
print 'doing something...'
def maybe_do_it(hesitant=False):
if hesitant:
do_something = lambda: 'did nothing'
result = do_something()
print result
maybe_do_it()
Run Code Online (Sandbox Code Playgroud)
这段代码的结果是:
File "scope_test.py", line 10, in <module>
maybe_do_it()
File "scope_test.py", line 7, in maybe_do_it
result = do_something()
UnboundLocalError: local variable 'do_something' referenced before assignment
Run Code Online (Sandbox Code Playgroud)
但是这段代码按照预期印刷了"做了些什么......":
def do_something():
print 'doing something...'
def maybe_do_it(hesitant=False):
result = do_something()
print result
maybe_do_it()
Run Code Online (Sandbox Code Playgroud)
即使if语句中的条件从未执行过,该函数是如何被覆盖的?这种情况发生在Python 2.7中 - 在Python 3中是否相同?
这是对这个问题的一个后续行动.
换句话说,问题2是:是否存在以下代码(在必要的语法中)起作用的语言:
def f(): print ('f')
def g():
f()
f = 42
g()
Run Code Online (Sandbox Code Playgroud) 这个问题是关于Python变量范围的问题的后续问题.其他问题q1,q2和答案可以在SO上找到,甚至更多.官方Python文档和PEP 3104应该解释细节,但它们对我来说似乎并不完全不言自明.
我试图解决的主题是重构包含nonlocal/ global通过在一级层次结构上/下移动该代码的代码.
我不明白的是Python参考中这句话的含义:
与全局语句中列出的名称不同,非本地语句中列出的名称必须引用封闭范围中的预先存在的绑定(无法明确确定应创建新绑定的范围).
给出以下全局范围的代码:
var = 0
def outer():
global var # line A
var = 1
def inner():
nonlocal var # line B
var = 2
print('inner:', var)
inner()
print('outer:', var)
outer()
print('main:', var)
Run Code Online (Sandbox Code Playgroud)
执行会引发错误:
SyntaxError: no binding for nonlocal 'var' found
Run Code Online (Sandbox Code Playgroud)
代码可以工作(当然,如果任何一行A被注释掉,则会有不同的语义:
inner: 2
outer: 2
main: 0
Run Code Online (Sandbox Code Playgroud)
或B行被注释掉:
inner: 2
outer: 1
main: 1
Run Code Online (Sandbox Code Playgroud)
但是,在上面的例子中,并且因为nonlocal应该将var绑定到"封闭范围",我会预期A行将外部/ …
我UnboundLocalError最近碰到了这个案子,这看起来很奇怪:
import pprint
def main():
if 'pprint' in globals(): print 'pprint is in globals()'
pprint.pprint('Spam')
from pprint import pprint
pprint('Eggs')
if __name__ == '__main__': main()
Run Code Online (Sandbox Code Playgroud)
哪个产生:
pprint is in globals()
Traceback (most recent call last):
File "weird.py", line 9, in <module>
if __name__ == '__main__': main()
File "weird.py", line 5, in main
pprint.pprint('Spam')
UnboundLocalError: local variable 'pprint' referenced before assignment
Run Code Online (Sandbox Code Playgroud)
pprint显然受到以下声明的约束globals,并将受到约束locals.有人可以解释为什么它不满意pprint在globals这里解决绑定?
编辑:由于回复良好,我可以用相关术语澄清我的问题:
在编译时,标识符pprint被标记为帧的本地.执行模型是否区分本地标识符绑定在框架内的哪个位置?它可以说,"引用全局绑定直到这个字节码指令,此时它已经反弹到本地绑定",或者执行模型没有考虑到这一点?
上周五我参加了面试,不得不回答以下问题:为什么这段代码会引发异常(UnboundLocalError: local variable 'var' referenced before assignment在包含的行上var += 1)?
def outer():
var = 1
def inner():
var += 1
return var
return inner
Run Code Online (Sandbox Code Playgroud)
我无法给出正确答案; 这个事实让我心烦意乱,当我回到家时,我很难找到合适的答案.好吧,我已经找到了答案,但现在有别的东西,让我困惑.
我必须事先说,我的问题更多的是关于设计语言时做出的决定,而不是关于它是如何工作的.
所以,请考虑这段代码.内部函数是一个python闭包,var并不是本地的outer- 它存储在一个单元格中(然后从单元格中检索):
def outer():
var = 1
def inner():
return var
return inner
Run Code Online (Sandbox Code Playgroud)
反汇编看起来像这样:
0 LOAD_CONST 1 (1)
3 STORE_DEREF 0 (var) # not STORE_FAST
6 LOAD_CLOSURE 0 (var)
9 BUILD_TUPLE 1
12 LOAD_CONST 2 (<code object inner at 0x10796c810)
15 LOAD_CONST 3 …Run Code Online (Sandbox Code Playgroud) 因此,我经常按照以下模式编写代码:
_list = list(range(10)) # Or whatever
_list = [some_function(x) for x in _list]
_list = [some_other_function(x) for x in _list]
Run Code Online (Sandbox Code Playgroud)
等等
我现在在另一个问题上看到一条评论,它解释了这种方法每次如何创建一个新列表,最好对现有列表进行变异,如下所示:
_list[:] = [some_function(x) for x in _list]
Run Code Online (Sandbox Code Playgroud)
这是我第一次看到此明确建议,我想知道其中的含义是什么:
1)突变是否节省内存?大概是在重新分配后对“旧”列表的引用将降为零,而“旧”列表将被忽略,但是在此之前会有延迟,此时我可能会使用比我使用时所需的更多内存重新分配而不是更改列表?
2)使用变异有计算成本吗?我怀疑就地更改某些内容比创建一个新列表并删除旧列表更昂贵?
在安全性方面,我编写了一个脚本对此进行测试:
def some_function(number: int):
return number*10
def main():
_list1 = list(range(10))
_list2 = list(range(10))
a = _list1
b = _list2
_list1 = [some_function(x) for x in _list1]
_list2[:] = [some_function(x) for x in _list2]
print(f"list a: {a}")
print(f"list b: {b}")
if __name__=="__main__":
main()
Run Code Online (Sandbox Code Playgroud)
哪个输出:
list a: [0, …Run Code Online (Sandbox Code Playgroud) 我正在教我的自我python,我正在将一些示例代码翻译成这个
class Student(object):
def __init__( self, name, a,b,c ):
self.name = name
self.a = a
self.b = b
self.c = c
def average(self):
return ( a+b+c ) / 3.0
Run Code Online (Sandbox Code Playgroud)
这几乎是我想要的课程定义
稍后在main方法中我创建一个实例并调用它 a
if __name__ == "__main__" :
a = Student( "Oscar", 10, 10, 10 )
Run Code Online (Sandbox Code Playgroud)
这就是我如何找出变量a中声明main可用的方法average ,并使该方法的工作,我必须键入 self.a + self.b + self.c代替
这个的基本原理是什么?
我发现了相关问题,但我真的不知道它们是否大致相同
我遇到了一些令我困惑的代码.这是一个显示这个的最小例子:
# of course, the ... are not part of the actual code
some_var = {"key1":"value1" ... "keyN":"valueN"}
def some_func():
v = some_var["key1"]
Run Code Online (Sandbox Code Playgroud)
代码有效,但我可以some_var直接访问的事实让我困惑.我最后一次编写一些Python代码时,我记得要编写some_func这样的代码:
def some_func():
global some_var
v = some_var["key1"]
Run Code Online (Sandbox Code Playgroud)
我在Windows 7 PC上使用Python 2.7.1.2.7版本中有什么变化允许这个吗?