1. 列表与 * 操作

Python 中,* 操作符与 list 结合使用,实现元素复制。

复制 5 个空列表:

In [1]: [[]] * 5
Out[1]: [[], [], [], [], []]In [2]: a = [[]] * 5In [3]: a
Out[3]: [[], [], [], [], []]In [4]:

填充两个元素:

In [4]: a[0].extend([1,2,3])In [5]: a[1].extend([4,5,6])

期望应该为:

[[1,3,5],[2,4,6],[],[]]

实际为:

In [6]: a
Out[6]:
[[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6],[1, 2, 3, 4, 5, 6]]

原来 * 操作复制出的 a[0]a[1]...a[5],在内存中标识符是相等的,实现的仅仅是浅复制。

In [7]: id(a[0])
Out[7]: 1641831703560In [8]: id(a[1])
Out[8]: 1641831703560In [9]: id(a[2])
Out[9]: 1641831703560In [10]: id(a[3])
Out[10]: 1641831703560

在这种场景下,希望实现 id[0]id[1] 不相等,修改 a[1] 不会影响 a[0]
不使用 *,使用列表生成式,复制出 5 个不同 id 的内嵌列表,这样就能避免赋值互不干扰的问题。

In [12]: b = [[] for _ in range(5)]In [13]: b
Out[13]: [[], [], [], [], []]In [14]: id(b[0])
Out[14]: 1641875609928In [15]: id(b[1])
Out[15]: 1641875595080In [16]: id(b[2])
Out[16]: 1641875822344In [17]: b[0].extend([1,2,3])In [18]: b[1].extend([4,5,6])In [19]: b
Out[19]: [[1, 2, 3], [4, 5, 6], [], [], []]In [20]:

2. 删除列表元素

假设列表有重复元素,要删除列表中指定的元素,看下面代码:

In [20]: def del_list(a, x):...:     for i in a:...:         if i == x:...:             a.remove(i)...:     return a...:     In [21]: a = [1,2,3,2,4]In [22]: del_list(a, 2)
Out[22]: [1, 3, 4]In [23]: del_list([1,2,3,4,3,4,3], 2)
Out[23]: [1, 3, 4, 3, 4, 3]In [24]: del_list([1,2,3,4,3,4,3], 3)
Out[24]: [1, 2, 4, 4]In [25]: del_list([1,3,5,3,2], 3)
Out[25]: [1, 5, 2]

可以看到上面的删除都是正确的,再来看下面的代码

In [26]: del_list([1,3,3,3,3,5], 3)
Out[26]: [1, 3, 3, 5]

可以看出,删除结果仍然是包含 3 , 为什么呢?

遍历列表 aremove 一次,移掉位置 i 后的所有元素索引都要减一。所以,一旦删除的元素,重复出现在列表中,就总会漏掉一个该删除的元素。

正确做法,找到被删除元素后,删除,同时下次遍历索引不加一;若未找到,遍历索引加一。

一般来讲,尽量避免在列表迭代的过程中对列表进行删除、更新操作。

3. 函数默认参数为空

Python 函数的参数可设为默认值。如果一个默认参数类型为 list ,默认值为设置为 []
有下面函数:

In [27]: def add_list(value, volume=[]):...:     if volume is None:...:         volume = []...:     length = len(volume)...:     for i in range(length):...:         volumn[i] = i + value...:     return volume...:

调用 add_list 函数, val 值为 10, volume 默认值,函数返回 ret 为空列表。

In [28]: ret = add_list(10)In [29]: ret
Out[29]: []In [30]:

然后,我们向空列表 ret 中,分别添加值 1、2,打印 ret ,结果符合预期

In [30]: ret.append(1)In [31]: ret.append(2)In [32]: ret
Out[32]: [1, 2]

同样方法,再次调用 add_list 函数,第二个参数还是取默认值。预期返回值 ret 还是空列表,但是结果却出人意料!

In [41]: ret = add_list(10)In [42]: ret
Out[42]: [10, 11]

为什么返回值为 [10,11] 呢? 按照出现的结果,我们猜测 [1, 2] + 10 后,不正是 [11,12]。

原来调用函数 add_list 时,默认参数 volume 取值为默认值时,并且 volume 作为函数的返回值。再在函数外面做一些操作,再次按照默认值调用,并返回。整个过程,默认参数 volumeid 始终未变。

通过增加打印我们可以看到,确实是默认参数 volumeid 始终未变。

In [45]: ret = add_list(10)
volume id is 1641863237000In [46]: ret.append(1)In [47]: ret.append(2)In [48]: ret
Out[48]: [1, 2]In [49]: ret = add_list(10)
volume id is 1641863237000In [50]: ret
Out[50]: [10, 11]

为了避免这个隐藏的坑,函数的默认参数值切记不能设置为 [],而是为 None。这样即便按照默认值调用多次,也会规避此风险。

In [53]: def add_list(value, volume=None):...:     print("volume id is {}".format(id(volume)))...:     if volume is None:...:         volume = []...:     length = len(volume)...:     for i in range(length):...:        volume[i] = i + value...:     return volume...:     In [58]: ret = add_list(10)
volume id is 1929553104In [59]: ret
Out[59]: []In [60]: ret.append(1)In [61]: ret.append(2)In [62]: ret
Out[62]: [1, 2]In [63]: ret = add_list(10)
volume id is 1929553104In [64]: ret
Out[64]: []

4. {} 和 ()

单个元素要被识别为元组,必须在括号后面加个逗号 , 详见如下代码:

In [65]: a = (10)In [66]: type(a)
Out[66]: intIn [67]: b = (10,)In [68]: type(b)
Out[68]: tuple

创建集合与字典,它们都用一对 {},但是默认返回字典,而不是集合。要想创建空集合,可使用内置函数 set()

In [69]: d = {}In [70]: type(d)
Out[70]: dictIn [71]: s = set()In [72]: type(s)
Out[72]: set

5. 多值赋值顺序

多值赋值是先计算出等号右侧的所有变量值后,再赋值给等号左侧变量。

In [73]: a, b = 1, 2In [74]: a, b = b+1, a+b In [75]: a, b
Out[75]: (3, 3)

Python 常见的坑汇总相关推荐

  1. Pytorch常见的坑汇总

    来自 | 知乎   作者 | 郁振波 地址 | https://zhuanlan.zhihu.com/p/7792356 编辑 | 深度学习这件小事公众号 本文仅作学术分享,如有侵权,请联系删除 最近 ...

  2. Python常见web框架汇总

    目前,有非常多的Python框架,用来帮助你更轻松的创建web应用.这些框架把相应的模块组织起来,使得构建应用的时候可以更快捷,也不用去关注一些细节(例如socket和协议),所以需要的都在框架里了. ...

  3. Python常见问题解决办法汇总

    1.(unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX esc ...

  4. python替代hadoop_Python连接Hadoop数据中遇到的各种坑(汇总)

    最近准备使用Python+Hadoop+Pandas进行一些深度的分析与机器学习相关工作.(当然随着学习过程的进展,现在准备使用Python+Spark+Hadoop这样一套体系来搭建后续的工作环境) ...

  5. python字符串find函数-python常见字符串处理函数与用法汇总

    本文实例讲述了python常见字符串处理函数与用法.分享给大家供大家参考,具体如下: 1.find 作用:在一个较长字符串中查找子串.返回子串所在位置的最左端索引,如果没有找到则返回-1.如果指定 b ...

  6. js字符串replace替换多个_汇总几大python常见字符串处理函数与用法(建议收藏)...

    前言: 这篇文章主要介绍了python常见字符串处理函数与用法,结合实例形式详细分析了Python字符串操作函数find.join.replace及split功能.使用技巧与操作注意事项,需要的朋友可 ...

  7. python代码大全下载-最全Python算法实现资源汇总!

    原标题:最全Python算法实现资源汇总! 整理 | Rachel 责编 | Jane 出品 | Python大本营(ID:pythonnews) [导语]数据结构与算法是所有人都要学习的基础课程,自 ...

  8. python常用代码入门-最全Python算法实现资源汇总!

    原标题:最全Python算法实现资源汇总! 整理 | Rachel 责编 | Jane 出品 | Python大本营(ID:pythonnews) [导语]数据结构与算法是所有人都要学习的基础课程,自 ...

  9. python编程入门与案例详解-quot;Python小屋”免费资源汇总(截至2018年11月28日)...

    原标题:"Python小屋"免费资源汇总(截至2018年11月28日) 为方便广大Python爱好者查阅和学习,特整理汇总微信公众号"Python小屋"开通29 ...

最新文章

  1. 领计算机二级证材料,计算机二级证书怎么领
  2. 破解百度网盘的Pandownload开发者被捕,让人唏嘘
  3. Python高性能HTTP客户端库requests的使用
  4. 5.1 API : SVC
  5. POI设置单元格颜色及枚举颜色对照
  6. php 安装scws,SCWS分词扩展在windows下的安装方法
  7. 如何用java线程池做分批次查询处理 java线程池ThreadPoolExecutor的使用
  8. 前端架构设计第四课 Babel构建公共库实战
  9. 操作系统 银行家算法 安全性检查
  10. maven profile <filtering>true</filtering>的作用
  11. Deferred Decal
  12. latex 两个表格并排放置
  13. 重塑汽车的最新5G标准
  14. 使用 pip 快速安装 OpenCV
  15. 使用HTTPie测试Web服务
  16. 使用selenium操控浏览器爬取QQ音乐
  17. 5G时代下,射频器件、PCB等电子元器件产业面临的机遇与挑战
  18. 字节跳动面试凉经(挂三面)
  19. HTML5 全屏 API
  20. Android source code gerrit

热门文章

  1. 2022-2028年中国粘胶纤维市场投资分析及前景预测报告
  2. Pass Infrastructure基础架构(下)
  3. 内存缓存LruCache的简单使用
  4. git push 时不用每次都输入密码的方法
  5. Django 第三方引用富文本编辑器6.1
  6. Django 定义模型2.1
  7. [C] [字节跳动] [编程题] 手串
  8. Python break语句,continue语句,pass 语句
  9. intent传递有没有大小限制,是多少?
  10. DocumentsContract cannot be resolved