嵌套函数声明的范围
Scope of nested function declarations
我有以下代码:
def function_reader(path):
line_no = 0
with open(path, "r") as myfile:
def readline():
line_no +=1
return myfile.readline()
Python 不断返回:
UnboundLocalError: local variable 'line_no' referenced before assignment
执行时line_no +=1
。
我知道问题是嵌套函数声明在 python 中有奇怪的作用域(尽管我不明白为什么要这样编程)。我主要想知道是否有一种简单的方法可以帮助 python 解析引用,因为我真的很喜欢它提供的功能。
不幸的是,在 Python 2.x 中没有办法做到这一点。嵌套函数只能读取封闭函数中的名称,不能重新分配它们。
一个变通方法是制作 line_no
列表,然后更改其单个项目:
def function_reader(path):
line_no = [0]
with open(path, "r") as myfile:
def readline():
line_no[0] += 1
return myfile.readline()
然后您可以通过 line_no[0]
访问行号。下面是演示:
>>> def outer():
... data = [0]
... def inner():
... data[0] += 1
... inner()
... return data[0]
...
>>> outer()
1
>>>
这个解决方案有效,因为我们没有重新分配名称 line_no
,只是改变它引用的对象。
请注意,在 Python 3.x 中,使用 nonlocal
statement:
可以轻松解决此问题
def function_reader(path):
line_no = 0
with open(path, "r") as myfile:
def readline():
nonlocal line_no
line_no += 1
return myfile.readline()
获取下一行并跟踪行号的更 Pythonic 方法是使用 enumerate 内置函数:
with open(path, "r") as my file:
for no, line in enumerate(myfile, start=1):
# process line
这将适用于所有当前 Python 版本。
很难说您在这里试图通过使用闭包实现什么。但是问题是,使用这种方法,当您从外部函数 return readline
时,您将以 ValueError: I/O operation on closed file
结束,或者如果您 return readline()
来自外部函数。
如果您只想重复调用 readline()
或遍历文件并记住当前行号,那么最好使用 class:
class FileReader(object):
def __init__(self, path):
self.line_no = 0
self.file = open(path)
def __enter__(self):
return self
def __iter__(self):
return self
def next(self):
line = next(self.file)
self.line_no += 1
return line
def readline(self):
return next(self)
def __exit__(self, *args):
self.file.close()
用法:
with FileReader('file.txt') as f:
print next(f)
print next(f)
print f.readline()
print f.line_no # prints 3
for _ in xrange(3):
print f.readline()
print f.line_no # prints 6
for line in f:
print line
break
print f.line_no # prints 7
我有以下代码:
def function_reader(path):
line_no = 0
with open(path, "r") as myfile:
def readline():
line_no +=1
return myfile.readline()
Python 不断返回:
UnboundLocalError: local variable 'line_no' referenced before assignment
执行时line_no +=1
。
我知道问题是嵌套函数声明在 python 中有奇怪的作用域(尽管我不明白为什么要这样编程)。我主要想知道是否有一种简单的方法可以帮助 python 解析引用,因为我真的很喜欢它提供的功能。
不幸的是,在 Python 2.x 中没有办法做到这一点。嵌套函数只能读取封闭函数中的名称,不能重新分配它们。
一个变通方法是制作 line_no
列表,然后更改其单个项目:
def function_reader(path):
line_no = [0]
with open(path, "r") as myfile:
def readline():
line_no[0] += 1
return myfile.readline()
然后您可以通过 line_no[0]
访问行号。下面是演示:
>>> def outer():
... data = [0]
... def inner():
... data[0] += 1
... inner()
... return data[0]
...
>>> outer()
1
>>>
这个解决方案有效,因为我们没有重新分配名称 line_no
,只是改变它引用的对象。
请注意,在 Python 3.x 中,使用 nonlocal
statement:
def function_reader(path):
line_no = 0
with open(path, "r") as myfile:
def readline():
nonlocal line_no
line_no += 1
return myfile.readline()
获取下一行并跟踪行号的更 Pythonic 方法是使用 enumerate 内置函数:
with open(path, "r") as my file:
for no, line in enumerate(myfile, start=1):
# process line
这将适用于所有当前 Python 版本。
很难说您在这里试图通过使用闭包实现什么。但是问题是,使用这种方法,当您从外部函数 return readline
时,您将以 ValueError: I/O operation on closed file
结束,或者如果您 return readline()
来自外部函数。
如果您只想重复调用 readline()
或遍历文件并记住当前行号,那么最好使用 class:
class FileReader(object):
def __init__(self, path):
self.line_no = 0
self.file = open(path)
def __enter__(self):
return self
def __iter__(self):
return self
def next(self):
line = next(self.file)
self.line_no += 1
return line
def readline(self):
return next(self)
def __exit__(self, *args):
self.file.close()
用法:
with FileReader('file.txt') as f:
print next(f)
print next(f)
print f.readline()
print f.line_no # prints 3
for _ in xrange(3):
print f.readline()
print f.line_no # prints 6
for line in f:
print line
break
print f.line_no # prints 7