What is the output of the following code ? Please explain
def exten``dList(val, list=[]): list.append(val) return list list1 = extendList(10) list2 = extendList(123,[]) list3 = extendList('a') print "list1 = %s" % list1 print "list2 = %s" % list2 print "list3 = %s" % list3 How to modify extendList The definition of can produce the following expected behavior ? answer : The output of the above code will be : list1 = [10, 'a'] list2 = [123] list3 = [10, 'a']
Many people mistakenly think list1=[10],list3=[‘a’], Because they think every time extendList When called , The default values of the list parameters will be set to []. But the reality is , The new default list is created only once when the function is defined . When extendList No specific parameters are specified list Invocation time , This group of list The value of will then be used . This is because expressions with default parameters are evaluated when the function is defined , Not calculated at the time of the call . therefore list1 and list3 Is to operate on the same default list ( Calculation ) Of . and list2 Is to operate on a separate list ( Calculation ) Of .( By passing a self owned empty list as the value of the list parameter ).
extendList The definition of can be modified as follows . Even though , Create a new list , There are no specific list parameters .
The following code may produce the desired results .
def extendList(val, list=None): if list is None: list = [] list.append(val) return list Through the above modification , The output will become : list1 = [10] list2 = [123] list3 = ['a']
What will be the output of the following code ? Please explain .
def multipliers(): return [lambda x : i * x for i in range(4)] print [m(2) for m in multipliers()]
How do you modify the above multipliers The definition of produces the desired results ?
answer :
The output of the above code is [6, 6, 6, 6] ( It's not what we thought [0, 2, 4, 6]). The reason for the above problems is Python Delay binding of closures . This means that when an internal function is called , The value of the parameter is searched in the closure . therefore , When any multipliers() When the returned function is called ,i The value of will be found in the nearby range .
At that time , Whether the returned function is called or not ,for The cycle is complete ,i Given the final value 3.
therefore , Each time the function returned is multiplied by the value passed 3, Because the value of the previous code is 2, They all end up returning 6.(3*2)
It happened that ,《The Hitchhiker’s Guide to Python》 Also pointed out , With the lambdas There is also a widely misunderstood point of knowledge about functional correlation , But with this case Dissimilarity . from lambda There is nothing special about the functions created by expressions , It's actually with def The function created is the same .
Here are some ways to solve this problem . One solution is to use Python generator .
def multipliers(): for i in range(4): yield lambda x : i * x
Another solution is to create a closure , Use the default function to bind immediately .
def multipliers(): return [lambda x, i=i : i * x for i in range(4)] Another alternative is , Use partial functions : from functools import partial from operator import mul def multipliers(): return [partial(mul, i) for i in range(4)]
What will be the output of the following code ? Please explain
class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print Parent.x, Child1.x, Child2.x Child1.x = 2 print Parent.x, Child1.x, Child2.x Parent.x = 3 print Parent.x, Child1.x, Child2.x answer : The output will be : 1 1 1 1 2 1 3 2 3
What puzzles or surprises many people is why the last line of output is 3 2 3 instead of 3 2 1? Why is it changing parent.x At the same time, it has also changed child2.x Value ? But at the same time, it hasn't changed Child1.x Value ? The key to this answer is , stay Python in , Class variables are passed internally in the form of dictionaries .
If a variable name is not found in the dictionary under the current class , In a more advanced class ( Like its parent class ) Search until the referenced variable name is found .( If the reference variable name is not found in its own class and higher-level class , Will cause a property error .)
therefore , Set... In the parent class x = 1, Let variables x class ( With values 1) Can be referenced in its class and its subclasses to . That's why the output of the first printed statement is 1 1 1.
therefore , If any of its subclasses is overridden ( For example, , When we execute a statement Child.x = 2), This value is only modified in subclasses . That's why the output of the second print statement is 1 2 1.
Final , If this value is modified in the parent class ,( For example, , When we execute a statement Parent.x = 3), This change will affect values that have not overridden subclasses ( In this case is Child2) That's why the output of the third print statement is 3 2 3.
The following code is in Python2 What will the next output be ? Please explain
def div1(x,y): print "%s/%s = %s" % (x, y, x/y) def div2(x,y): print "%s//%s = %s" % (x, y, x//y) div1(5,2) div1(5.,2) div2(5,2) div2(5.,2.) stay Python3 How will the result be different ?( Of course , Suppose the above print statement is converted to Python3 The grammar of ) answer : stay Python2 in , The output of the above code will be 5/2 = 2 5.0/2 = 2.5 5//2 = 2 5.0//2.0 = 2.0
By default ,Python 2 Automatically perform shaping calculations if both are integers . therefore ,5/2 The result is 2, and 5./2 The result is 2.5 Be careful , stay Python2 in , You can override this behavior by adding the following references .
from future import division
At the same time, pay attention to ,// The operator will always perform integer division , Regardless of the type of operator . That's why even in Python 2 in 5.0//2.0 The result is 2.0.
However, in Python3 in , There is no such feature , for example , When both ends are shaped , It doesn't perform plastic Division
therefore , stay Python3 in , The results will be as follows :
5/2 = 2.5 5.0/2 = 2.5 5//2 = 2 5.0//2.0 = 2.0 What will be the output of the following code ? list = ['a', 'b', 'c', 'd', 'e'] print list[10:]
answer :
The following code will output [], Will not produce IndexError error . As expected , Try using more than the number of members index To get members of a list .
for example , Try to get list[10] And later members , It can lead to IndexError.
However , Try to get the slice of the list , At the beginning index Exceeding the number of members will not produce IndexError, It just returns an empty list .
This has become a particularly disgusting problem , Because there are no errors when running , Lead to bug It's hard to track .
Consider the following code snippet :
1. list = [ [ ] ] * 5 2. list # output? 3. list[0].append(10) 4. list # output? 5. list[1].append(20) 6. list # output? 7. list.append(30) 8. list # output? 2、4、6、8 What results will be output on the line ? Try to explain . answer : The output is as follows : [[], [], [], [], []] [[10], [10], [10], [10], [10]] [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]] [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30]
Explain the following :
The output of the first line is intuitively easy to understand , for example list = [ [ ] ] * 5 Is simply created 5 An empty list .
However , Understanding expressions list=[ [ ] ] * 5 The key point is that it doesn't create a list of five separate lists , Instead, it is a list created with five references to the same list .
Only to understand this point , We can better understand the next output .
list[0].append(10) take 10 Attach to the first list .
But because of all the 5 A list is the same list referenced , So the result will be :
[[10], [10], [10], [10], [10]]
Empathy ,list[1].append(20) take 20 Attach to the second list . But also because 5 A list is the same list referenced , So the output is now :
[[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]].
As a contrast , list.append(30) Is to attach the whole new element to the outer list , The result is :
[[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30].
Given a list of N numbers. Given a containing N A list of numbers .
Use a single list generator to generate a new list , The list contains only values that meet the following conditions :
(a) Even values
(b) The element is an even number of slices in the original list .
for example , If list[2] The value contained is even . Then this value should be included in the new list , Because this number is also in the even sequence of the original list (2 For the even ) On . However , If list[3] Contains an even number ,
answer :
That number should not be included in the new list , Because it's on the odd sequence of the original list . The simple solution to this problem is as follows :
[x for x in list[::2] if x%2 == 0]
for example , The given list is as follows :
list = [ 1 , 3 , 5 , 8 , 10 , 13 , 18 , 36 , 78 ]
List generator [x for x in list[::2] if x%2 == 0] The result is :
[10, 18, 78]
The steps that this expression works are , The first step is to take out the number of even slices , The second step is to eliminate all odd numbers .
Give subclasses of the following dictionaries :
class DefaultDict(dict): def __missing__(self, key): return [] Can the following code run ? Why? ? d = DefaultDict() d['florp'] = 127
answer :
Be able to run . When key When missing , perform DefaultDict class , The instance of the dictionary will automatically instantiate this sequence .