python - What's the advantage of using yield in __iter__()? -
what advantage of using generator(yield
) inside __iter__()
function? after reading through python cookbook understand "if want generator expose state user, don’t forget can implement class, putting generator function code in __iter__()
method."
import io class playyield: def __init__(self,fp): self.completefp = fp def __iter__(self): line in self.completefp: if 'python' in line: yield line if __name__ =='__main__': io.open(r'k:\data\somefile.txt','r') fp: playyieldobj = playyield(fp) in playyieldobj: print
questions:
- what state means here?
- what advantage of using
yield
inside__iter__ ()
instead of using separate functionyield
?
without generator functions, have implement this, if want follow best practices:
in [7]: class iterablecontainer: ...: def __init__(self, data=(1,2,3,4,5)): ...: self.data = data ...: def __iter__(self): ...: return iterablecontaineriterator(self.data) ...: in [8]: class iterablecontaineriterator: ...: def __init__(self, data): ...: self.data = data ...: self._pos = 0 ...: def __iter__(self): ...: return self ...: def __next__(self): ...: try: ...: item = self.data[self._pos] ...: except indexerror: ...: raise stopiteration ...: self._pos += 1 ...: return item ...: in [9]: container = iterablecontainer() in [10]: x in container: ...: print(x) ...: 1 2 3 4 5
of course, above example contrived, point. generators, can be:
in [11]: class iterablecontainer: ...: def __init__(self, data=(1,2,3,4,5)): ...: self.data = data ...: def __iter__(self): ...: x in self.data: ...: yield x ...: ...: in [12]: list(iterablecontainer()) out[12]: [1, 2, 3, 4, 5]
as state, well, it's - objects can have state, e.g. attributes. can manipulate state @ runtime. could following, although, highly inadvisable:
in [19]: class iterablecontaineriterator: ...: def __init__(self, data): ...: self.data = data ...: self._pos = 0 ...: def __iter__(self): ...: return self ...: def __next__(self): ...: try: ...: item = self.data[self._pos] ...: except indexerror: ...: raise stopiteration ...: self._pos += 1 ...: return item ...: def rewind(self): ...: self._pos = min(0, self._pos - 1) ...: in [20]: class iterablecontainer: ...: def __init__(self, data=(1,2,3,4,5)): ...: self.data = data ...: def __iter__(self): ...: return iterablecontaineriterator(self.data) ...: in [21]: container = iterablecontainer() in [22]: = iter(container) in [23]: next(it) out[23]: 1 in [24]: next(it) out[24]: 2 in [25]: it.rewind() in [26]: next(it) out[26]: 1 in [27]: next(it) out[27]: 2 in [28]: next(it) out[28]: 3 in [29]: next(it) out[29]: 4 in [30]: next(it) out[30]: 5 in [31]: it.rewind() in [32]: next(it) out[32]: 1
Comments
Post a Comment