Python loop traps (reprint)

The for loop in Python and other languages ​​for cycle work is not the same, today takes you deep understanding of Python for loop and see how it works and why it works that way.

Loop trap

We first look at Python loop "trap" in our understanding of the work of the cycle, and then look at these traps in the end is how occur.

Trap 1: cycle twice

Now let's suppose you have a list of numbers, and the square of a generator used to return these numbers:

>>> nums = [1, 2, 3, 4]
>>> squares = (n**2 for n in nums)

We can generate a tuple object passed to the constructor, a tuple can be obtained:

>>> tuple(squares)
(1, 4, 9, 16)

This time, if we then passed to the constructor of the object sumfunction, and normally should return these numbers and bar:

>>> sum(squares)
0

Returns a 0, is holding chin first.

Trap 2: check that

We still use the above list of numbers and generator:

>>> nums = [1, 2, 3, 4]
>>> squares = (n**2 for n in nums)

If I squares contain Builder 9, the answer is yes, Ruoguo I ask again?

Do you dare to promise you
Do you dare to promise you
>>> 9 in squares
True
>>> 9 in squares
False

Found, the second is not working -

Trap 3: unpacking

Now suppose there is a dictionary:

>>> counts = {1:'a', 2:'b'}

Then, we were unpacking the dictionary with multiple variables:

>>> x,y = counts

What do you think this time, x and y would be?

>>> x
1
>>> y
2

We only got the key.

Here, we start to understand the cycle of works under Python, then anti so far as to see these traps issue.

Some concepts

First, let's understand some basic concepts:

And can be iterative sequence

May iteration refers to any thing can be used for looping through can be an iterative means you can traverse, anything that can be traversed is iterative.

for item in some_iterable:
    print(item)

Sequence is a common type of iterations can, such as a list of tuples, strings and the like.

Iterative sequence is, it has a number of features, which start from index 0, the index length does not exceed the length of the sequence; they have a sequence length; and they can be sliced.

Python Most things are possible iterations, but you can not mean that it is an iterative sequence. As set, the dictionary, and the file generator iteration it is available, but they are not sequences.

>>> my_set = {1, 2, 3}
>>> my_dict = {'k1': 'v1', 'k2': 'v2'}
>>> my_file = open('some_file.txt')
>>> squares = (n**2 for n in my_set)

Conclude that, anything can be used for loop through iterations are available, one type of iterative sequence can, Python there are many other kinds of iteration can type.

Iterator

Iterator that can drive things to an iterative object. You can get an iterator from any iteration object, you can also use it to manually iterator iterator to traverse.

Here are three iterables: a collection of tuples and a string:

>>> nums = {1,2,3,4}
>>> coors = (4,5,6)
>>> words = "hello hoxis"

We can use Python's built-in functions iter, these can be obtained from the object to the iterator iteration:

>>> iter(nums)
<setiterator object at 0x7fa8c194ad70>
>>> iter(coors)
<tupleiterator object at 0x7fa8c1959610>
>>> iter(words)
<iterator object at 0x7fa8c19595d0>

Once we have an iterator, we can use its built-in function next()to get its next value:

>>> nums = {1,2,3,4}
>>> num_iter = iter(nums)
>>> next(num_iter)
1
>>> next(num_iter)
2
>>> next(num_iter)
3
>>> next(num_iter)
4
>>> next(num_iter)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Ruoguo iteration coming to an end, that is not the next value, it will throw an StopIterationexception. In other words, it will not continue to get the first cycle takes a value.

It is not to force a little ignorant?

  • Iterables is an iterative thing
  • Iteration object is actually a proxy traversal iterables
  • Iterator no length, they can not be indexed.
  • The only useful thing you can use an iterator to do is to pass it to the built-in nextfunction, or cycle through them
  • You can use list()the function to convert a list iterator
>>> nums = {1,2,3,4}
>>> num_iter = iter(nums)
>>> next(num_iter)
1
>>> list(num_iter)
[2, 3, 4]
>>> list(num_iter)
[]

Ruoguo want to convert it to the list again, obviously, it is to get an empty list.

In fact, this is an important characteristic of iterators: inert , can only be used once, can only loop through once. And, before we call the next () function, it does not do anything. Therefore, we can create an infinite iterator, create an infinitely long list are not, as you will run out of memory!

Iterables not necessarily iterators, but the iterator must be iterative:

Objects You may iteration? Iterator?
Iterables Not necessarily
Iterator
Builder
List ×

In fact, Python, there are many iterators, generators iterators, Python's many built-in type is iterator. For example, Python's enumerateand reversedobjects are iterators. zip, mapAnd filteralso an iterator; file object is also an iterator.

Python for loop

In fact, Python is not traditional for loop, what is traditional for loop?

We look in Java for loop:

int[] integers = {1234};
for (int j = 0; j<integers.length; j++) {
    int i = integers[j];
    System.out.println(i);
}

This is a C风格for loop, JavaScript, C, C ++, Java, PHP and other programming languages have a lot of style for this cycle, but Python does not.

The Python for loop we call, precisely, should be foreach loop:

numbers = [1, 2, 3, 5, 7]
for n in numbers:
    print(n)

And C风格differs from that of the for loop, Python for loop index variable no, no index variable initialization, an increase of bounds checking and index variables.

This is different from the Python for loop!

Use the index?

You may wonder, Python for loop are using the index at the bottom, here we use a while loop manually and indexes to traversal:

>>> nums = [1,2,3,4]
>>> i = 0
>>> while i < len(nums):
...     print(num[i])
...     i += 1
...
0
1
2
3

For a list, so traversal is possible, but does not mean for all iterables, it only applies to the sequence .

For example, we use this method to traverse a set, get an exception:

>>> set = {1,2,3}
>>> i = 0
>>> while i < len(set):
...     print(set[i])
...     i += 1
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: 'set' object does not support indexing

Because the sequence is not set, it does not support indexing through.

We can not each iteration of Python objects to traverse an index manually. For those who are not iterators sequence, it is not going to work.

Not for the realization of the cycle

From the above, Python for loop index not used, it is used iterator. Let's look at how it works.

From the foregoing, we learned iterators and iter, next function, and now we can try to do for loop to iterate over an iterable object.

Here is a normal for loop:

def funky_for_loop(iterable, action_to_do):
    for item in iterable:
        action_to_do(item)

We must try to achieve the above logic for a method loop iterators and while, generally the following steps:

  1. Get given iterables iterator;
  2. Call the iterator's next () method to get the next item;
  3. The current item of data is processed;
  4. If captured StopIteration, then stop the loop
def funky_for_loop(iterable, action_to_do):
    iterator = iter(iterable)
    while not done_looping:
        try:
            item = next(iterator)
        except StopIteration:
            break
        else:
            action_to_do(item)

Python cycle work substantially as the underlying code is driving for loop iterations.

Once again returns to the loop trap

Trap 1: depleted iterator

1 trap, because the generator is an iterator, iterator is inert, is disposable, in case of having traversed once, and then sums them, a 0 is returned.

Trap 2: partially consumed iterator

In trap 2, we asked whether the two 9 exist in the same builder, get a different answer.

This is because, for the first time when asked, Python has this generator has been traversed, ie, call next () function to find 9, after finding returns True, the second time to ask 9 whether there will be from the location times continue next () to find.

>>> nums = [1,2,3,4,5]
>>> squares = (n**2 for n in nums)
>>> 9 in squares
True
# 此时打印出来
>>> list(squares)
[16, 25]

Trap 3: unpacking is iterative

When iterating directly in the dictionary, it is to get the key:

>>> counts = {1:'a',2:'b'}
>>> for i in counts:
...     print(i)
... 
1
2

And when unpacking the dictionary, and the dictionary traversal is the same, they are dependent on the iterator protocol, thus resulting also key.

to sum up

Sequence is an iterator, but not all iterators are sequences. Iterator can not be through the loop twice, can not access their length, can not use the index.

Python iterator is the most basic form can be iterative. If you want to do in a code inert iteration, please consider iterators, and consider using a generator or function generator expression.

Finally, remember that, in each iteration of Python are dependent on the iterator protocol, understanding the iterator protocol is the key to understanding the cycle of Python.

Original link: https://opensource.com/article/18/3/loop-better-deeper-look-iteration-python

Guess you like

Origin www.cnblogs.com/mountain2011/p/11427159.html