Fuzzy semantics in Python syntax

Time:2022-5-25
catalogue
  • 1. The slice does not perform cross-border inspection and error reporting
  • 2. Creation of empty list
  • 3. Delayed binding of closures

1. The slice does not perform cross-border inspection and error reporting

What will be the output of the following code?

?
1
2
list = ['a', 'b', 'c', 'd', 'e']
print list[10:]

The following code will output an empty list [], and will not generateIndexErrorWrong. As expected, try to get the members of a list with an index that exceeds the number of members.

For example, try to get list[10] And subsequent members will lead toIndexError .

However, the list of attempts to get slices beginsindexIf the number of members exceeds, it will not be generatedIndexError,Instead, it simply returns an empty list.

This becomes a particularly disgusting problem, because there are no errors during operation, which makes it difficult to track the bug.

2. Creation of empty list

?
1
2
3
4
5
6
7
8
1ist = [[ ]] * 5
list  # output?
list[0].append(10)
list  # output?
list[1].append(20)
list  # output?
list.append (30)
list  # output?

What results will be output in lines 2, 4, 6 and 8? Try to explain.

The output results are as follows:

?
1
2
3
4
[[],[],[],[],[]]
[[10],[10],[10],[10],[10]]
[[10,20],[10,20],[10,20]]
[[10,20],[10,20],[10,20],[10,20],[10,20],30]

The output of the first line is intuitively easy to understand, for example list = [ [ ] ] * 5 Simply create five empty lists. However, understanding expressionslist=[ [ ] ] * 5 The key point is that it does not create a list containing five independent lists, but a list containing five references to the same list. Only by understanding this can we better understand the next output results.

3. Delayed binding of closures

What will be the output of the following code? Please explain.

?
1
2
3
4
5
6
7
8
'''
No one answers the problems encountered in learning? Xiaobian created a python learning exchange group: 531509025
Look for like-minded friends to help each other. There are also good video learning tutorials and PDF e-books in the group!
'''
def multipliers():
    return [lambda x : i*x for i in range(4)]
 
print [m(2) for m in multipliers()]

How do you modify the abovemultipliersDoes the definition of produce the desired results?
The output of the above code is [6, 6, 6, 6] , not what we think [0, 2, 4, 6]

The reasons for the above problems arePythonDeferred binding of closures. This means that when the internal function is called, the value of the parameter is looked up in the closure. Therefore, when anymultipliers()When the returned function is called, the value of I will be searched in the nearby range. At that time, whether the returned function is called or not, the for loop has been completed and I is given the final value of 3.

Therefore, each time the returned function is multiplied by the passed value 3, because the value passed by the previous code is 2, and they finally return 6 (3 * 2). As it happens,《The Hitchhiker's Guide to Python》It is also pointed out that there is also a widely misunderstood knowledge point related to Lambdas function, but it is related to thiscasedissimilarity. fromlambdaThere is nothing special about the function created by expression. It is actually the same as the function created by def.

Here are some ways to solve this problem.

One solution is to use a python generator.

?
1
2
def multipliers():
    for i in range(4): yield lambda x : i * x

Another solution is to create a closure that uses the default function to bind immediately.

?
1
2
def multipliers():
    return [lambda x, i=i : i * x for i in range(4)]

An alternative is to use a partial function:

?
1
2
3
4
5
from functools import partial
from operator import mul
 
def multipliers():
    return [partial(mul, i) for i in range(4)]

This is the end of this article on fuzzy semantics in Python syntax. For more information about Python syntax, please search previous articles on developeppaper or continue to browse the relevant articles below. I hope you will support developeppaper in the future!