Python 如何使对象具有与with和for语句之前的open()相同的行为
我想在Python中创建一个类,该类接收一个文件名,并返回一个对象,该对象可以由上下文管理器处理,也可以由for循环调用 基本上,文件将逐行解析(iterable)。该类将把每一行分割成一个定义的模式,并在迭代的每一步返回一个值元组 我知道我需要实现Python 如何使对象具有与with和for语句之前的open()相同的行为,python,python-3.x,iteration,contextmanager,Python,Python 3.x,Iteration,Contextmanager,我想在Python中创建一个类,该类接收一个文件名,并返回一个对象,该对象可以由上下文管理器处理,也可以由for循环调用 基本上,文件将逐行解析(iterable)。该类将把每一行分割成一个定义的模式,并在迭代的每一步返回一个值元组 我知道我需要实现\uu iter\uuuuu,\uuuu next\uuuuuuuu方法,以使其易于使用,但我不清楚如何继续。该文件是我的类属性之一,我希望迭代器在每次迭代时生成解析的行 我也知道我需要实现\uuuuuuuuuuuuuuuuuuuuuuuuuu和\u
\uu iter\uuuuu
,\uuuu next\uuuuuuuu
方法,以使其易于使用,但我不清楚如何继续。该文件是我的类属性之一,我希望迭代器在每次迭代时生成解析的行
我也知道我需要实现\uuuuuuuuuuuuuuuuuuuuuuuuuu
和\uuuuuuuuuuuuuuu
方法,但这对我来说也有点模糊
class myfile:
def __init__(self,file,**kwargs):
self._file = open(file,'r')
def __del__(self):
self._file.close()
def __enter__(self):
# Not sure what am I supposed to return here
def __exit__(self):
self._file.close()
def __iter__(self):
# What iterator must be returned
def __next__(self):
return parseLine(x)
def parseLine(self,line):
#Stuff:
return *values
我不是在寻找开箱即用的代码,而是想了解每种神奇的方法都需要什么才能正常工作,从而获得所需的行为
更新:
我最终决定用以下方法来做:
class myfile:
def __init__(self,file,**kwargs):
self._file = open(file,'r')
def __del__(self):
self._file.close()
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self._file.close()
def __iter__(self):
for fline in self._file:
yield self.parseLine(fline)
def parseLine(self,line):
# Stuff
return *values
它似乎有我想要的行为。当我执行以下操作时,它会起作用:
with myfile(r'x.txt') as pf:
for i in pf:
print(i)
这是实现这一目标的好方法吗?它足够像蟒蛇吗?在这两种情况下都只需返回
self
您的类本身就是迭代器(因为您提供了一个\uuuuuuuuuuuuuuuuuuuu next\uuuuuuuuuu
方法),如果您没有\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu的特殊值,请输入\uuuuuuuuuuuuuuu
事实上,这正是file对象在这两种情况下所做的:
>>> fobj = open('/dev/null')
>>> fobj.__enter__() is fobj
True
>>> fobj.__iter__() is fobj
True
对于\uuuu iter\uuuuu
,如果您想支持对对象的独立迭代,您应该返回一个不同的对象;然后,该新对象将返回的self
,并提供\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu下一个方法,而不是此类
对于\uuuu输入\uuuu
,您将返回任何方便用户在with
语句中绑定的内容。例如,某些数据库连接对象返回新的游标对象,因此您可以执行以下操作:
with conn as cursor:
# handle a transaction, using the already produced cursor
请注意,更新后的版本将从\uuuuuuuiTER\uuuuuu
返回一个生成器,它是每次调用iter(myfile(“…”)
时的一个新迭代器。这些迭代器并不是真正独立的,因为iter(fileobj)
将始终返回文件对象本身,因此在一个生成器上进行迭代将随着文件位置的提高而影响其他生成器
此外,由于文件对象是它们自己的迭代器,因此可以直接在文件对象上使用,但不能在对象上使用
一个更好的解决方案是坚持返回self
,并让您的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu方法执行解析:
def __iter__(self):
return self
def __next__(self):
return self.parseLine(next(self._file))
谢谢你的回答,你能检查一下我所做的更新是否正确吗correct@jlandercy:有点;您的\uuuuuuuuuuuuuuuuu iter\uuuuuuuu
现在每次调用时都返回一个新的生成器(一种迭代器);这意味着您现在可以为文件对象创建单独的迭代器。在这种情况下,这没关系,因为文件对象本身仍然只返回self
,而独立迭代器并不是真正独立的。@jlandercy:这可能很好;但是您也可以使用def\uu next\uu(self):返回self.parseLine(next(self.\u文件))
而不是创建生成器。@jlandercy:这种方法的缺点是next(yourobject)
不起作用,而next(fileobj)
起作用。