该解决方案会让您感到惊讶。

> Image by FreePhotosART from Pixabay

尝试解决以下问题,然后检查以下答案。

提示:所有问题都有共同点,因此在解决其余问题之前检查第一个问题的解决方案可以减轻挑战。

问题1

假设我们有几个变量:

x = 1

y = 2

l = [x, y]

x += 5

a = [1]

b = [2]

s = [a, b]

a.append(5)

l和s的打印结果是什么?

跳到解决方案

问题2

让我们定义一个简单的函数:

def f(x, s=set()):

s.add(x) print(s)

如果您决定,将会发生什么:

>>f(7)

>>f(6, {4, 5})

>>f(2)

跳到解决方案

问题3

让我们定义两个简单的函数:

def f():    l = [1]    def inner(x):        l.append(x)        return l    return innerdef g():    y = 1    def inner(x):        y += x        return y    return inner

以下命令将产生什么结果?

>>f_inner = f()

>>print(f_inner(2))

>>g_inner = g()

>>print(g_inner(2))

跳到解决方案

您对自己的回答有多自信? 让我们看看您是否正确。

解决问题1

>>print(l)

[1, 2]

>>print(s)

[[1, 5], [2]]

为什么第二个列表对第一个元素a.append(5)的更改有反应,但是第一个列表完全忽略x + = 5的类似变化?

解决问题2

让我们看看发生了什么:

>>f(7){7}

>>f(6, {4, 5}){4, 5, 6}

>>f(2){2, 7}

等待,最后输出不是{2}吗?

解决问题3

输出将是以下内容:

>>f_inner = f()

>>print(f_inner(2))[1, 2]

>>g_inner = g()

>>print(g_inner(2))

UnboundLocalError: local variable 'y' referenced before assignment

为什么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)更改原始对象,因此list s"看到"更改。

问题2的解释

def f(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}。

这就是为什么您不应该使用可变的默认参数的原因。 在这种情况下,应按以下方式修改功能:

def f(x, s=None):    if s is None:        s = set()    s.add(x)    print(s)

问题3的解释

def f():    l = [1]    def inner(x):        l.append(x)        return l    return innerdef g():    y = 1    def inner(x):        y += x        return y    return inner>>f_inner = f()>>print(f_inner(2))[1, 2]>>g_inner = g()>>print(g_inner(2))UnboundLocalError: local variable ‘y’ referenced before assignment

在这个问题中,我们处理闭包-内部函数记住定义时它们的封闭名称空间的外观。 或至少应该如此-第二个功能保持扑克面孔,就像从未听说过其外部作用域一样。

这是为什么? 当我们执行l.append(x)时,在定义时创建的可变对象被修改,但是变量l仍然指向内存中的相同地址。 但是,尝试更改第二个函数y + = x中的不可变变量会导致y指向内存中与以前不同的地址-原始y将不再被记住,因此导致UnboundLocalError。

结论

Python中可变对象与不可变对象之间的区别非常重要。 请注意这一点,以避免出现本文所述的奇怪行为。 特别是:

不要使用可变的默认参数。

不要尝试在内部函数中更改不可变的闭包变量。

请随意分享其他示例,这些示例可能是由于您在响应中误用了可变的和不变的对象而导致的潜在问题。

(本文翻译自Tomelisse的文章《Can you solve these 3 (seemingly) easy Python problems?》,参考:https://levelup.gitconnected.com/can-you-solve-these-3-seemingly-easy-python-problems-2c793967cd2c)

strcat第二个参数变吗_您能解决这3个(看似)简单的Python问题吗?相关推荐

  1. basemap安装_【我是解决安装问题系列_1】Mac python basemap安装

    「2020/3/21更新」 附basemap网盘下载地址⏬ Python需要跳过的安装的坑太太太太多了!!!!! 最近看<利用python进行数据分析>这本书,到可视化的部分,看着最后的例 ...

  2. python编写接口自动化脚本_简单的python http接口自动化脚本

    摘抄:今天给大家分享一个简单的python脚本,使用python进行http的接口测试,脚本很简单,逻辑是:读取excel写好的测试用例,然后根据excel中的用例内容进行调用,判断预期结果中的返回值 ...

  3. java 变长参数 知乎_变长参数探究

    前言 变长参数,指的是函数参数数量可变,或者说函数接受参数的数量可以不固定.实际上,我们最开始学C语言的时候,就用到了这样的函数:printf,它接受任意数量的参数,向终端格式化输出字符串.本文就来探 ...

  4. listen函数的第二个参数_【图像处理】OpenCV系列十七 --- 几何图像变换函数详解(一)...

    上一篇我们学习了仿射变换的warpAffine函数,知道了如何用这个函数对图像进行旋转.平移等操作,那么本节我们一起来学习一下与仿射变换相关的其他函数以及相关的几何图像变换. 一.convertMap ...

  5. java sort 第二个参数_详解java Collections.sort的两种用法

    Collections是一个工具类,sort是其中的静态方法,是用来对List类型进行排序的,它有两种参数形式: public static > void sort(List list) { l ...

  6. Python 程序设计(第二版)董付国_清华大学出版社_习题答案与分析【针对8.4及其之前的】

    更多精彩内容:(没有设置公众号获得,麻烦动动小手~谢谢) CSDN下载:Python编程无师自通电子书,[美]科里·奥尔索夫(Cory Althoff)-文档类-CSDN下载 百度云:链接:https ...

  7. C语言strftime()函数 (格式化时间)(注意第二个参数size_t maxsize一定要大于第三个参数const char *format指向字符串的长度)

    需包含:C 标准库 - <time.h> 文章目录 描述 声明 参数 返回值 实例 使用☞坑(注意第二个参数size_t maxsize一定要大于第三个参数const char *form ...

  8. matlab 变长参数,变长参数函数的概念

    分享一个2015年华为笔试知识点:变长参数函数 变长参数的函数即参数个数可变.参数类型不定 的函数. 设计一个参数个数可变.参数类型不定的函数是可能的,最常见的例子是printf函数.scanf函数和 ...

  9. sgd 参数 详解_代码笔记--PC-DARTS代码详解

    DARTS是可微分网络架构搜搜索,PC-DARTS是DARTS的拓展,通过部分通道连接的方法在网络搜索过程中减少计算时间的内存占用.接下来将会结合论文和开源代码来详细介绍PC-DARTS. 1 总体框 ...

最新文章

  1. 十三水牌型 图片_鬼灭之刃:鳄鱼揭开十三型的秘密,缘一亲自演示
  2. 01Django是如何工作的
  3. Raft只读操作实现要点
  4. java 年计算_用Java计算leap年
  5. eclipse快速定位java对应的class
  6. 获取本机IP_考虑多网卡的情况
  7. 图片自适应css代码(转)
  8. 计算机审计的概念的论文,论文:浅谈计算机审计中的数据分析
  9. 在MyEclipse中如何查看Spring/Hibernate/Struts/JDK等源码的方法
  10. 笔记(3)——Clustering the tagged web
  11. android selector(转)
  12. MySQL索引的原理,B+树、聚集索引和二级索引的结构分析
  13. abb机器人goto指令用法_ABB机器人的指令详细介绍!!!
  14. 频谱、幅度谱、功率谱和能量谱
  15. ROS 教程2 机器人雷达建图 蒙特卡洛定位 导航 路径规划 仿真
  16. 1217: 青蛙(二)
  17. 计算机软件著作权登记的申请流程是什么
  18. 免费获取ADS1299的AD原理图和封装!
  19. 任务签到表(2006.11.20)
  20. MOOS例程HelloWorld-详细注释

热门文章

  1. HashMap的小知识点
  2. iOS 和常见的离屏渲染Say Goodbye!
  3. wxWidgets第十七课 采用AGG渲染库
  4. 深度学习框架中的魔鬼:探究人工智能系统中的安全问题
  5. Java Lock的使用
  6. Win10文件管理器那些你不知道的秘密
  7. MATLAB 线性运算之图像相加去噪
  8. Ckeditor 的加载顺序
  9. curl Unsupported protocol: https 问题解决
  10. 2016年最值得关注的16个网页设计趋势