以下代码的输出结果是什么?请解释defexten``dList(val,list=[]):list.append(val)returnlistlist1=extendList(10)list2=extendList(123,[])list3=extendList('a')print"list1=%s"%list1print"list2=%s"%list2print"list3=%s"%list3如何修改extendList的定义以产生以下预期行为?答:上面代码的输出会是:list1=[10,'a']list2=[123]list3=[10,'a']很多人会误认为list1=[10],list3=['a'],因为他们认为每次调用extendList时,list参数的默认值都会设置为[]。但实际发生的是,新的默认列表仅在定义函数时创建一次。当在没有特定参数列表的情况下调用extendList时,随后将使用列表值的集合。这是因为带有默认参数的表达式是在定义函数时计算的,而不是在调用函数时计算的。所以list1和list3对同一个默认列表进行操作(计算)。list2在单独的列表上运行(计算)。(通过传递自己的空列表作为列表参数的值)。extendList的定义可以修改如下。虽然,要创建一个新列表,没有特定的列表参数。下面的一段代码可能能够产生预期的结果。defextendList(val,list=None):iflistisNone:list=[]list.append(val)returnlist经过上面的修改,输出会变成:list1=[10]list2=[123]list3=['a']以下代码的输出是什么?请解释。defmultipliers():return[lambdax:i*xforiinrange(4)]print[m(2)forminmultipliers()]您将如何修改上述乘数的定义以产生所需的结果?答:上面代码的输出是[6,6,6,6](不是我们想的[0,2,4,6])。上面的问题是由于Python闭包的延迟绑定引起的。这意味着当调用内部函数时,会在闭包内部查找参数的值。因此,当调用multipliers()返回的任何函数时,将在附近的范围内查找i的值。至此,不管返回函数是否??被调用,for循环已经完成,i被赋予最终值3。因此,每个返回函数都会将传入的值乘以3,因为上面传入的值code为2,最后都返回6。(3*2)巧的是,《The Hitchhiker’s Guide to Python》也指出了lambdas函数相关的也有一个被广泛误解的知识点,但与本案例不同。lambda表达式创建的函数没有什么特别之处,其实和def创建的函数是一样的。这里有一些方法可以解决这个问题。一种解决方案是使用Python生成器。defmultipliers():foriinrange(4):yieldlambdax:i*x另一种解决方案是创建一个使用默认函数立即绑定的闭包。defmultipliers():return[lambdax,i=i:i*xforiinrange(4)]另一种方法是使用部分函数:fromfunctoolsimportpartialfromoperatorimportmuldefmultipliers():return[partial(mul,i)foriinrange(4)]以下代码的输出是什么?请解释classParent(object):x=1classChild1(Parent):passclassChild2(Parent):passprintParent.x,Child1.x,Child2.xChild1.x=2printParent.x,Child1.x,Child2.xParent.x=3printParent.x,Child1.x,Child2.x答案:输出将是:111121323让很多人感到困惑或惊讶的是为什么最后一行输出323而不是3二十一?为什么更改parent.x也会更改child2.x的值?但同时不改变Child1.x的值?这个答案的关键在于,在Python中,类变量在内部作为字典传递。如果在当前类下的字典中没有找到变量名,则在更高级别的类(例如其父类)中搜索穷尽,直到找到引用的变量名。(如果在自己的类和更高的类中都找不到引用变量名,则会引发属性错误。)因此,在父类中设置x=1使得变量xclass(值为1)在其类中可用并且它的子类被引用。这就是为什么第一个print语句的输出是111。因此,如果它的任何子类覆盖了一个值(例如,当我们执行语句Child.x=2时),该值只会在子类中被修改。这就是为什么第二个print语句的输出是121。最后,如果在父类中修改了这个值,(比如我们执行语句Parent.x=3时),这个修改会影响那些在子类中没有被覆盖的值(本例中为Child2))这就是为什么第三个print语句的输出是323。以下代码在Python2下的输出结果是什么?请解释defdiv1(x,y):print"%s/%s=%s"%(x,y,x/y)defdiv2(x,y):print"%s//%s=%s"%(x,y,x//y)div1(5,2)div1(5.,2)div2(5,2)div2(5.,2.)在Python3下结果会有什么不同?(当然,假设上面的打印语句转换为Python3语法)答:在Python2中,上面代码的输出默认为5/2=25.0/2=2.55//2=25.0//2.0=2.0,Python2如果两者都是整数,则自动执行整数计算。因此,5/2结果为2,5./2结果为2.5请注意,在Python2中,您可以通过添加以下引用来覆盖此行为。fromfutureimportdivision还要注意//运算符将始终执行整数除法,而不管运算符的类型如何。这就是为什么5.0//2.0即使在Python2中也会得到2.0。但是在Python3中没有这样的功能,例如当两端都是整数时它不执行整数除法所以在Python3中,结果将是:5/2=2.55.0/2=2.55//2=25.0//2.0=2.0以下代码的输出是什么?list=['a','b','c','d','e']printlist[10:]答:下面的代码会输出[],不会出现IndexError。尝试按预期获取索引超过成员数的列表成员。例如,尝试获取list[10]及以后的成员将导致IndexError。但是,尝试从超过成员数的索引开始获取列表的一部分不会引发IndexError,而只会返回一个空列表。这成为一个特别令人讨厌的陷阱,因为它运行时没有错误,使得错误难以追踪。考虑以下代码片段:1.list=[[]]*52.list#output?3.列表[0].追加(10)4。列出#输出?5。列表[1].append(20)6.列出#输出?7.list.append(30)8.list#输出?2,4,6,8会输出什么?试着解释。答:输出如下:[[],[],[],[],[]][[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]解释如下:第一行的输出直观易懂,例如list=[[]]*5只是创建了5个空列表。然而,关于表达式list=[[]]*5的关键是,它不是创建一个包含五个单独列表的列表,而是创建一个包含对同一列表的五个引用的列表。只有理解了这一点,我们才能更好地理解接下来的输出。list[0].append(10)将10添加到第一个列表。但是由于所有5个列表都引用同一个列表,结果将是:[[10],[10],[10],[10],[10]]同样,list[1].append(20)Append20到第二个列表。但是由于5个列表引用同一个列表,现在输出为:[[10,20],[10,20],[10,20],[10,20],[10,20]].In相反,list.append(30)将整个新元素附加到外部列表,因此结果是:[[10,20],[10,20],[10,20],[10,20],[10,20],30].给定一个包含N个数字的列表。给定一个包含N个数字的列表。使用单个列表推导生成一个新列表,该列表仅包含满足(a)偶数值和(b)原始列表的偶数切片的元素的值。例如,如果list[2]包含偶数值。那么这个值应该包含在新列表中,因为这个数字也在原始列表的偶数序列上(2是偶数)。但是,如果list[3]包含一个偶数,则回答:该数字不应包含在新列表中,因为它在原始列表中的奇数序列上。这个问题的一个简单的解决方案如下:[xforxinlist[::2]ifx%2==0]例如,给定一个列表如下:list=[1,3,5,8,10,13,18,36,78]列表生成的结果[xforxinlist[::2]ifx%2==0]是:[10,18,78]这个表达式的工作步骤是,第一步取出偶数切片的数,第二步取出所有奇数。给定以下字典的子类:classDefaultDict(dict):def__missing__(self,key):return[]下面的代码可以工作吗?为什么?d=DefaultDict()d['florp']=127答案:有效。当key丢失时,执行DefaultDict类,字典的实例会自动实例化这个数组。
