当前位置: 首页 > 科技观察

你能解决这3个(看似)简单的Python问题吗?

时间:2023-03-15 20:06:11 科技观察

尝试解决以下问题,然后检查下面的答案。提示:所有问题都有一些共同点,因此在解决其余问题之前检查第一个问题的解决方案可以缓解挑战。问题1假设我们有几个变量:x=1y=2l=[x,y]x+=5a=[1]b=[2]s=[a,b]a.append(5)printoflandsWhat's结果?跳至解决方案问题2让我们定义一个简单的函数:deff(x,s=set()):s.add(x)print(s)如果您决定:>>f(7)>>f(6,{4,5})>>f(2)?跳到解决方案问题3让我们定义两个简单的函数:deff():l=[1]definener(x):l.append(x)returnlreturninnerdefg():y=1definner(x):y+=xreturnyreturninner下面的命令是什么生产?>>ff_inner=f()>>print(f_inner(2))>>gg_inner=g()>>print(g_inner(2))跳至解决方案您对自己的答案有多自信?让我们看看你是否正确。?解决问题1>>print(l)[1,2]>>print(s)[[1,5],[2]]为什么第二个list对第一个元素a.append(5)有变化响应,但第一个列表完全忽略了x+=5中的类似变化?解决问题2让我们看看会发生什么:>>f(7){7}>>f(6,{4,5}){4,5,6}>>f(2){2,7}等等,是吗'最终输出{2}?解决问题3输出如下:>>ff_inner=f()>>print(f_inner(2))[1,2]>>gg_inner=g()>>print(g_inner(2))UnboundLocalError:localvariable'y'referencedbeforeassignment为什么g_inner(2)不输出3?f()的内部函数如何记住它的外部作用域,而g()的内部函数不记得?他们其实是一样的!如果我告诉你这些奇怪的行为与Python中可变对象和不可变对象之间的区别有关,请解释一下怎么办?列表之类的东西,集合或字典之类的可变对象可以就地改变(变异)。诸如整数、字符串和元组之类的不可变对象不能——对此类对象的“更改”会导致创建新对象。问题1的解释x=1y=2l=[x,y]x+=5a=[1]b=[2]s=[a,b]a.append(5)>>print(l)[1,2]>>print(s)[[1,5],[2]]由于x是不可变的,操作x+=5不会改变原始对象,而是创建一个新对象。列表的第一个元素仍然指向原始对象,因此它的值保持不变。对于可变对象a,a.append(5)更改原始对象,因此lists“看到”更改。第2题的解释deff(x,s=set()):s.add(x)print(s)>>f(7){7}>>f(6,{4,5}){4,5,6}>>f(2){2,7}前两个输出非常有意义:首先将值7添加到默认空集,得到{7},然后将值6添加到集{4,5},得到{4,5,6}。但是随后发生了一件奇怪的事情:值2被添加到默认的空集而不是{7}的集合。为什么?可选参数s的默认值只被计算一次——只有在第一次调用s时才会被初始化为一个空集。由于s在调用f(7)之后是可变的,因此它被就地修改。第二次调用f(6,{4,5})不会影响默认参数-提供的集合{4,5}隐藏它,换句话说,{4,5}是一个不同的变量。对f(2)的第三次调用使用与第一次调用相同的s变量,但s没有重新初始化为空集-使用其先前的值{7}。这就是为什么你不应该使用可变的默认参数。在这种情况下,函数应修改如下:deff(x,s=None):ifsisNone:s=set()s.add(x)print(s)问题3的解释deff():l=[1]definener(x):l.append(x)returnlreturninnerdefg():y=1definner(x):y+=xreturnyreturninner>>ff_inner=f()>>print(f_inner(2))[1,2]>>gg_inner=g()>>print(g_inner(2))UnboundLocalError:localvariable'y'referencedbeforeassignment在这个问题中我们处理闭包——内部函数在定义时记住它们的封闭命名空间是什么样子的。或者至少它应该——第二个函数保持扑克脸,就好像它的外部范围从未听说过一样。为什么是这样?当我们执行l.append(x)时,定义时创建的可变对象被修改,但变量l仍然指向内存中的相同地址。但是,尝试在第二个函数y+=x中更改不可变变量会导致y指向与之前不同的内存地址——原来的y将不再被记住,从而导致UnboundLocalError。结论Python中可变对象和不可变对象之间的区别非常重要。请注意这一点,以避免出现本文中描述的奇怪行为。特别是:不要使用可变的默认参数。不要试图改变内部函数中的不可变闭包变量。请随意分享您在响应中滥用可变和不可变对象可能引起的潜在问题的其他示例。