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

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:1097524789

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

问题1

假设我们有几个变量:

  1. x = 1
  2. y = 2
  3. l = [x, y]
  4. x += 5
  5. a = [1]
  6. b = [2]
  7. s = [a, b]
  8. a.append(5)

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

跳到解决方案

问题2

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

  1. def f(x, s=set()):
  2. s.add(x) print(s)

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

  1. >>f(7)
  2. >>f(6, {4, 5})
  3. >>f(2)

跳到解决方案

问题3

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

  1. def f():
  2. l = [1]
  3. def inner(x):
  4. l.append(x)
  5. return l
  6. return inner
  7. def g():
  8. y = 1
  9. def inner(x):
  10. y += x
  11. return y
  12. return inner

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

  1. >>ff_inner = f()
  2. >>print(f_inner(2))
  3. >>gg_inner = g()
  4. >>print(g_inner(2))

跳到解决方案

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

解决问题1

  1. >>print(l)
  2. [1, 2]
  3. >>print(s)
  4. [[1, 5], [2]]

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

解决问题2

让我们看看发生了什么:

  1. >>f(7){7}
  2. >>f(6, {4, 5}){4, 5, 6}
  3. >>f(2){2, 7}

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

解决问题3

输出将是以下内容:

  1. >>ff_inner = f()
  2. >>print(f_inner(2))[1, 2]
  3. >>gg_inner = g()
  4. >>print(g_inner(2))
  5. UnboundLocalError: local variable 'y' referenced before assignment

为什么g_inner(2)不输出3? f()的内部函数如何记住其外部范围,而g()的内部函数却不记得呢? 它们实际上是相同的!

说明

如果我告诉您这些怪异的行为与Python中可变对象和不可变对象之间的区别有关怎么办?

诸如列表,集合或字典之类的可变对象可以在适当位置进行更改(变异)。 不变的对象(如整数,字符串和元组)不能—此类对象的"更改"会导致创建新对象。

问题1的说明

  1. x = 1
  2. y = 2
  3. l = [x, y]
  4. x += 5
  5. a = [1]
  6. b = [2]
  7. s = [a, b]
  8. a.append(5)
  9. >>print(l)
  10. [1, 2]
  11. >>print(s)
  12. [[1, 5], [2]]

由于x是不可变的,因此操作x + = 5不会更改原始对象,而是创建一个新对象。 列表的第一个元素仍指向原始对象,因此其值保持不变。

对于可变对象a,a.append(5)更改原始对象,因此list s"看到"更改。

问题2的解释

  1. def f(x, s=set()):
  2. s.add(x)
  3. print(s)
  4. >>f(7)
  5. {7}
  6. >>f(6, {4, 5})
  7. {4, 5, 6}
  8. >>f(2)
  9. {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}。

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

  1. def f(x, s=None):
  2. if s is None:
  3. s = set()
  4. s.add(x)
  5. print(s)

问题3的解释

  1. def f():
  2. l = [1]
  3. def inner(x):
  4. l.append(x)
  5. return l
  6. return inner
  7. def g():
  8. y = 1
  9. def inner(x):
  10. y += x
  11. return y
  12. return inner
  13. >>ff_inner = f()
  14. >>print(f_inner(2))
  15. [1, 2]
  16. >>gg_inner = g()
  17. >>print(g_inner(2))
  18. UnboundLocalError: local variable ‘y’ referenced before assignment

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

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

结论

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

  • 不要使用可变的默认参数。
  • 不要尝试在内部函数中更改不可变的闭包变量。
  • 请随意分享其他示例,这些示例可能是由于您在响应中误用了可变的和不变的对象而导致的潜在问题。

您能解决这3个(看似)简单的Python问题吗?相关推荐

  1. hashcode的作用_看似简单的hashCode和equals面试题,竟然有这么多坑!

    hashCode()方法和equals()区别与联系这到面试题,看似简单,根据以往面试星友的情况来说,绝大部分人都不能很好的回答出来,要么没有逻辑,想到一句就说一句,要么抓不住重点,答非所问.从这个很 ...

  2. 绘图的尺寸_AutoCAD新功能:参数化绘图,绘制看似简单,实际复杂,案例详解...

    虽然很熟悉 CAD 软件的使用,但是对于CAD参数化绘图功能并不了解,甚至不知道.随着 CAD 版本的不断更新,功能越来越完善和强大,从AutoCAD2010 版本开始,增加了一个支持利用约束条件绘制 ...

  3. 看似简单的hashCode和equals面试题,竟然有这么多坑!

    作者:徐刘根,大家都喊我根哥! hashCode()方法和equals()区别与联系这到面试题,看似简单,根据以往面试星友的情况来说,绝大部分人都不能很好的回答出来,要么没有逻辑,想到一句就说一句,要 ...

  4. 拼多多看似简单,为什么很多的新手商家却亏钱了呢?

    大家好!我是面兜兜,关注面兜兜每天学习不同的店铺运营知识!今天,面兜兜要为大家分享的是关于拼多多开店的问题. 现如今,入驻拼多多的新手商家依然不少,而其中不乏很多的电商小白,由于是小白,没有什么经验, ...

  5. 计算机技术含量,有哪些看似简单却技术含量高的操作?

    感觉是个特别涨姿势的好问题,一进来感觉就能看半天的那种. 那么今天小编也来添砖加瓦一下,为这个问题贡献自己的一份绵薄之力. 对于这个问题,我们分享三个例子: 1.蒸汽计算机 2.榫卯 3.换挡 蒸汽计 ...

  6. 【转】【荐】看似简单的问题 静态方法和实例化方法的区别

    [转自]看似简单的问题 静态方法和实例化方法的区别 这是一个经常被时时提出来的问题,很多时候我们以为理解了.懂了,但深究一下,我们却发现并不懂. 方法是我们每天都在写得,很多程序员大多都使用实例化方法 ...

  7. equals的效率_看似简单的hashCode和equals面试题,竟然有这么多坑!

    点击上方"Java后端技术",选择"置顶或者星标" 你关注的就是我关心的! hashCode()方法和equals()区别与联系这到面试题,看似简单,根据以往面 ...

  8. 视错觉:从一个看似简单的自定义控件说起

    转载自: https://www.cnblogs.com/ludashi/p/4994520.html 视错觉:从一个看似简单的自定义控件说起 为什么要写今天这篇博客那就说来话长了,那是在一个大雪纷飞 ...

  9. 看似简单的搜索引擎,原来背后的数据结构和算法这么复杂?

    来源 | 码海 封图 | CSDN 付费下载于视觉中国 前言 我们每天都在用 Google, 百度这些搜索引擎,那大家有没想过搜索引擎是如何实现的呢,看似简单的搜索其实技术细节非常复杂,说搜索引擎是 ...

  10. win7忘记密码怎么办,Administrator忘记密码解决办法【完美、简单、有效】

    win7忘记密码怎么办,Administrator忘记密码解决办法[完美.简单.有效] 2012年06月12日  ⁄ 发现分享  ⁄ 评论数 1 今天同学的电脑登陆密码忘记了,win7操作系统,向我来 ...

最新文章

  1. [网摘学习]在Ubuntu上安装和配置OpenStack Nova之二
  2. 扫描服务器端口信息工具,服务器端口扫描工具
  3. 提升编程水平的靠谱方法
  4. python cv2 matchtemplate_OpenCV-Python系列十:模板匹配
  5. 我理解消化后的浮点数存储
  6. 时间管理 SMART 与 四象限
  7. 群晖docker安装Transmission下载器
  8. U8采购订单联查采购入库单
  9. ceph-cache-tier
  10. Web自动化测试学习笔记
  11. OpenJDK构建工具IcedTea 1.7发布
  12. 泛微OA前端经验总结
  13. 基于HTML+CSS+JavaScript的在线图书阅读网页设计
  14. 【微信小程序/云开发bug解决方案合集】持续更新中(最新22-11-21)
  15. 成功鲜有偶然:一览IT名人的教育成长经历
  16. pythontext函数用法汇总_Python - Text Summarization
  17. 520程序员的浪漫表白
  18. 三分钟认知Softmax和Sigmoid的详细区别
  19. linux查找以c开头的的文件夹,文件查找命令find详解
  20. CY62256 Static RAM 的数据读写操作

热门文章

  1. jquery-事件绑定
  2. TDengine安装
  3. OGG ORA-1403 NO DATA FOUND
  4. django 视图-----视图函数
  5. 网站登录JWT的实现
  6. 使用js简单实现javaMap
  7. LFS-构建自己的linux
  8. 卸载Oracle数据库(有图有真相)
  9. 面试:Websocket
  10. 面试官系统精讲Java源码及大厂真题 - 18 场景集合:并发 List、Map的应用场景