我有以下代码:
def function_reader(path):
line_no = 0
with open(path, "r") as myfile:
def readline():
line_no +=1
return myfile.readline()
Python不断返回:
UnboundLocalError:在赋值之前引用的局部变量'line_no'
执行line_no +=1
时。
我理解问题是嵌套函数声明在python中有奇怪的作用域(虽然我不明白它为什么用这种方式编程)。我主要想知道是否有一种简单的方法来帮助python解析引用,因为我真的很喜欢它提供的功能。
答案 0 :(得分:3)
不幸的是,在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()
答案 1 :(得分:1)
通过使用闭包很难说出你想要实现的目标。但问题是,使用这种方法,当你从外部函数返回ValueError: I/O operation on closed file
时,你将以readline
结束,如果从外部函数返回readline()
,则只返回第一行。
如果您只想重复调用readline()
或循环浏览文件并记住当前行号,那么最好使用一个类:
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
答案 2 :(得分:0)
获取下一行并跟踪行号的更多Pythonic方法是枚举内置:
with open(path, "r") as my file:
for no, line in enumerate(myfile, start=1):
# process line
这适用于所有当前的Python版本。