赋值前引用的局部变量

时间:2014-04-23 00:46:28

标签: python scope

我疯了。这个简单的回调函数无法识别在它的父作用域之前分配的变量。我收到local variable 'elapsed' referenced before assignment错误。为什么呢?

total = os.path.getsize(filename)
elapsed = 0

def progress_print(chunk):
    elapsed += len(chunk)  # elapsed is apparently unassigned??
    percent = float(elapsed) / float(total) * 100
    print '  Copied %s%%\033[A' % int(percent)

ftp.upload(filename, temp_path, callback=progress_print)

2 个答案:

答案 0 :(得分:4)

您正在尝试分配给全球。 Python让你明确地做到这一点。

def progress_print(chunk):
    global elapsed
    elapsed += len(chunk)

一般来说,这是一个非常好的迹象,表示您需要重构代码,直到您不再需要全局变量。

请注意,赋值和访问是不同的野兽 - 前者要求您显式声明全局变量,后者则不需要。举个例子,你的total变量是另一个全局变量,但你不会尝试赋值给它,因此python不会抱怨。

Programming FAQ详细介绍:

  

Python中的局部变量和全局变量有哪些规则?

     

在Python中,仅在函数内引用的变量是   隐含全球性。如果在任何地方为变量分配了新值   在函数体内,它被认为是一个本地的。如果是变量   在函数内部分配了一个新值,变量是   隐式本地,您需要明确地将其声明为“全局”。

     

虽然起初有点令人惊讶,但片刻的考虑解释了   这个。一方面,要求全局分配变量提供了一个   禁止意外的副作用。另一方面,如果全球化了   所有全局引用都需要,你将全局使用全局   时间。您必须将每个对内置的引用声明为全局   功能或导入模块的组件。这种混乱会   打败全球宣言的有用性   副作用。

答案 1 :(得分:0)

当你做

def progress_print(chunk):
    elapsed += len(chunk)

这里过去的是新的局部变量。因为你正在做+ =,这只不过是:

elapsed = elapsed + len(chunk)  

这里,elapsed没有用任何值初始化,这就是你得到错误的原因 - 在赋值之前引用了。

因此你需要这样做:

def progress_print(chunk):
    global elapsed
    elapsed += len(chunk)