📜 ⬆️ ⬇️

Iterate everything and everyone

image
As far as I could understand from my own experience, when switching to Python from another programming language, it is sometimes difficult to get used to his specific approach to cycles. For example, take the same for , which works in a completely different way than in other languages. I will take the liberty to tell that I myself at first was difficult to grasp, let alone use in my code, iterators. The thing is actually very useful, you just need to know how to use it correctly! ;)

APD : Only now I noticed that the topic of functional programming is more popular today than ever :) Thanks to comrade uj2 for opening such an interesting topic, I support!

Iterators are special objects that represent sequential access to data from a container. At the same time, the important role is played by the fact that the memory is not actually wasted, since intermediate data is provided as needed when requested, therefore, in fact, only the original data and the final result will remain in memory, and they can also be read and written using the file on the disk.
')
The iterator is convenient to use along with the sequence. Any object that supports an iterator interface has a next () method that allows you to move to the next stage of evaluation. To get an iterator over an object (for example, a list), you need to apply the iter () function to it. By the way, the already mentioned for loop also involves an iterator, only without additional dances - everything is done automatically. To handle complex data sets, you can connect the standard module itertools .

Let's create the simplest iterator manually:
testIt = iter([1, 2, 3, 4, 5])
print [x for x in testIt]

Of course, this is the simplest use of the for loop, just written a little differently.
"And what's new?" - you ask. Yes, in principle, nothing, just climbed a little deeper into the structure of processing sequences. But now, how do you like this: the function iter () can take not only a data structure, which so easily represents its iterator, but also two completely different arguments: a function without arguments and a stop value at which the iteration stops. Example:
def getSimple(state=[]):
if len(state) < 4:
state.append(" ")
return " "

testIt2 = iter(getSimple, None)
print [x for x in testIt2]

The example is based on the fact that in Python, if there is no explicit return of the value from the function, the value None is returned.

Now consider several functions that are based on iterators:

enumerate ()
Intended for numbering the data structure elements (including another iterator). Returns a list of tuples, in each of which the first element is a number (starting from zero), and the second is an element of the original iterator. Example:
>>> print [x for x in enumerate("abcd")]
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd')]

sorted ()
Iterator that performs the sort:
>>> sorted('avdsdf')
['a', 'd', 'd', 'f', 's', 'v']

itertools.chain ()
An iterator that allows you to combine two different iterators into one. Example:
from itertools import chain
it1 = iter([1,2,3])
it2 = iter([8,9,0])
for i in chain(it1, it2):
print i,

will result in "1 2 3 8 9 0".

itertools.count ()
Iterator, issuing infinite numbers, starting with the given:
for i in itertools.count(1):
print i,
if i > 100:
break

Result:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
96 97 98 99 100 101

itertools.cycle ()
Infinitely repeats a given sequence:
tango = [1, 2, 3]
for i in itertools.cycle(tango):
print i,

Result:
1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 3 2 3 1 3 3 1 3 3 1 3 3 3 2 3 1 3 3 1 3 3 3 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 3 3 3 3 1 2 3 1 2 3 1 3 3 3 3 1 3 3 1 2 3 3 3 3 3 2 3 1 2 3 1 2 3 1 2 3 1 ..

Also in this module there are analogues map () , starmap () , filter () and zip () , they are naturally called itertools.imap () , itertools.starmap () , itertools.ifilter () and itertools.izip ( ) . Their advantage is that, unlike their "ordinary" counterparts, they spend much less memory. There are also a couple of filters: itertools.takewhile () and itertools.dropwhile () :
for i in takewhile(lambda x: x > 0, [1, -2, 3, -3]):
print i,
for i in dropwhile(lambda x: x > 0, [1, -2, 3, -3]):
print i,

Result:
one
-2 3 -3

The fact is that takewhile () returns values ​​as long as the condition is true, and does not even take the remaining values ​​from the iterator (it does not take, and does not drain everything to the end!). And, conversely, dropwhile () does not produce anything while the condition is satisfied, but then it returns everything without a trace.

And finally, let's write our own iterator (almost finished Bender’s famous phrase)!

class Fibonacci:
""" N"""
def __init__(self, N):
self.n, self.a, self.b, self.max = 0, 0, 1, N
def __iter__(self):
# : next()
return self
def next(self):
if self.n < self.max:
a, self.n, self.a, self.b = self.a, self.n+1, self.b, self.a+self.b
return a
else:
raise StopIteration
# :
for i in Fibonacci(100):
print i,

Here, in fact, the whole basic theory. If you want to learn more subtleties - read the special literature. If you have any comments - I will be glad to hear :)

The article uses the materials of the lecture by Roman Arvievich Susi “Elements of functional programming”.

Source: https://habr.com/ru/post/50026/


All Articles