Python 列表和字典常踩坑即解决方案

目录
  • 一、关于列表
    • 1.问题描述
    • 2.解决方案
      • 方案一
      • 方案二
  • 二、关于字典
    • 1.问题描述
    • 2.解决方案
  • 结论

前言:

在Python中,如果我们想要在遍历一组数据的过程中,对这组数据进行修改,通常会出现许多问题,例如对列表进行上述操作时, 会忽略部分数据;遍历字典时,不能修改数据。本文针对这些问题,提出了多种解决方案。

一、关于列表

1.问题描述

在Python中,如果你试图在遍历一组数据的过程中,对其进行修改,这通常没什么问题。

例如:

l = [3, 4, 56, 7, 10, 9, 6, 5]

for i in l:
    if not i % 2 == 0:
        continue
    l.remove(i)
print(l)

上述这段代码遍历了一个包含数字的列表,为了去除掉所有偶数,直接修改了列表l。

然而,运行后输出却是:

[3, 56, 7, 9, 5]

等一下!输出似乎不对。最终的结果仍然含有一个偶数56。为什么没有成功去除这个数呢?我们可以尝试打印出 for循环遍历的所有元素,

运行如下代码:

l = [3, 4, 56, 7, 10, 9, 6, 5]
for i in l:
    print(i)
    if not i % 2 == 0:
        continue
    l.remove(i)
print(l)

这段代码的输出为:

3
4
7
10
6
[3, 56, 7, 9, 5]

从输出可以看出,for循环似乎没有访问列表中的所有元素。为了解for循环在内部究竟做了什么, 我们可以使用 iter 和 next 来模拟一下。

看看下面这个例子,我使用了ipython shell 来运行代码:

In [1]: l = [3, 4, 56, 7, 10, 9, 6, 5]
In [2]: # 把列表变成一个迭代器
In [3]: it = iter(l)
In [4]: # 使用 next() 方法来模拟 for循环
In [5]: next(it)
Out[5]: 3
In [6]: next(it)
Out[6]: 4
In [7]: # 移除一个迭代器已经访问过的元素
In [8]: l.remove(3)
In [9]: next(it)
Out[9]: 7
In [10]: # 注意此处跳过了56,我们可以再移除一个元素
In [11]: l.remove(4)
In [12]: next(it)
Out[12]: 9

上面这个实验揭示了:当你移除一个迭代器已经访问过的元素后,在下一次迭代时,会跳过右边的一个元素,直接访问下一个。

反之依然成立,即当开始迭代后,如果你在列表开头添加了一个元素,下次迭代时,可能会访问到已经迭代过的元素,

下面这段代码就出现了这种情况:

In[1]: l = [3, 4, 56, 7, 10, 9, 6, 5]
In[2]: it = iter(l)
In[3]: next(it)
Out[3]: 3
In[4]: next(it)
Out[4]: 4
In[5]: l.insert(0, 44)
In[6]: next(it)
Out[6]: 4

注意:当在列表头部添加了44后,4被访问了两次。

2.解决方案

为了解决上述问题,我们必须得确保:不能移除迭代器访问过的元素。

方案一

我们可以先对原列表进行翻转得到一个新列表,再对新列表进行迭代,并在原列表 l 中移除不符合条件的元素。

该方案代码如下:

l = [3, 4, 56, 7, 10, 9, 6, 5]
# 迭代翻转后的列表
for i in reversed(l):
    print(i)
    if not i % 2 == 0:
        continue
    l.remove(i)
print(l)

结果如下:

5
6
9
10
7
56
4
3
[3, 7, 9, 5]

注意:迭代器现在成功访问到了列表中的所有元素,并最终输出了只含有奇数的列表。

方案二

我们还可以在开始迭代前,先复制列表 l 。但是当列表 l 中的数据过多时,这样做显然比较耗费性能。

该方案代码如下:

l = [3, 4, 56, 7, 10, 9, 6, 5]
# 在这里使用 'l.copy()' 来对列表 l 进行浅拷贝
for i in l.copy():  
    print(i)   
    if not i % 2 == 0:     
        continue  
    l.remove(i)
print(l)

输出如下:

3
4
56
7
10
9
6
5
[3, 7, 9, 5]

该方案能保证迭代的顺序和移除元素的顺序相同。不过由于迭代和移除这两种操作针对的是两个不同的列表,因此顺序相同并不重要。

二、关于字典

1.问题描述

在对字典进行迭代时,不能修改字典。如下:

# {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
d = {k: k for k in range(10)}
for k, v in d.items():  
    if not v % 2 == 0:    
        continue  
    d.pop(k)

这段代码会产生 RuntimeError :

Traceback (most recent call last):  
  File "F:/Documents/pythonprojects/01practice/app.py", line 7, in <module>  
    for k, v in d.items():
RuntimeError: dictionary changed size during iteration

2.解决方案

我们可以先复制字典的所有 key ,随后在迭代 key 的过程中,移除不符合条件的元素。过程如下:

# {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9}
d = {k: k for k in range(10)}
# 这里复制了字典中的所有key值
# 没有复制整个字典
# 同时使用tuple()速度更快
for k in tuple(d.keys()):   
    if not d[k] % 2 == 0:    
        continue  
    d.pop(k)
    
print(d)

运行代码后输出如下:

{1: 1, 3: 3, 5: 5, 7: 7, 9: 9}

我们成功移除了字典中的所有偶数键值对!

结论

文中我们针对迭代一组数据时无法进行修改的问题,分别提出了不同的解决方案:如果想在遍历列表的时候,对列表进行修改, 我们可以先对原列表进行翻转或复制,从而得到一个新列表,随后在遍历新列表的过程中,修改原列表中的数据;如果我们想在遍历字典的时候,对字典进行修改,可以先复制字典的所有键值,然后在迭代键值的时候,修改字典中的数据。

到此这篇关于 Python 列表和字典常踩坑即解决方案的文章就介绍到这了,更多相关 Python 列表和字典 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python编程根据字典列表相同键的值进行合并

    目录 一.前言 两个列表的数据为: 期望合并的结果 二.实现分析 三.总结 一.前言 今天有粉丝咨询了一个问题,他现在有两个列表,它们的元素都为字典,且字典都有一个key为id,现在想把这两个字典根据id合并为一个字典,类型下面的效果: 两个列表的数据为: a_list = [{'id': 1, 'value': 11}, {'id': 2, 'value': 22}, {'id': 3, 'value': 33}] b_list = [{'id': 1, 'name': 'a'}, {'id'

  • python 如何读取列表中字典的value值

    目录 读取列表中字典的value值 获取字典的key和value 读取列表中字典的value值 list = [{"name": "推荐食谱", "1": "症状", "name1": "浑身忽冷忽热"}, {"name": "绿豆薏米饭"}, {"name": "芝麻"}] res = [item[key]

  • Python 列表推导式与字典推导式的实现

    目录 列表推导式 for 循环写法 列表推导式写法 列表推导式还支持嵌套 字典推导式 元组推导式与集合推导式 总结 在 Python 中推导式是一种非常 Pythonic 的知识,本篇博客将为你详细解答列表推导式与字典推导式相关的技术知识. 列表推导式 列表推导式可以利用列表,元组,字典,集合等数据类型,快速的生成一个特定需要的列表. 语法格式如下: [表达式 for 迭代变量 in 可迭代对象 [if 条件表达式]] if 条件表达式 非必选,学完列表推导式之后,你可以发现它就是 for 循环

  • C++程序的五大内存分区实力详解

    目录 1.栈内存区 1.1.调用函数时通过栈来传递函数的参数值 1.2.线程占用的栈内存是有上限的 2.堆内存区 3.全局/静态内存区 4.文字常量区 5.程序代码区 总结 C++程序在运行时所占用的内存区域,一般可分为栈内存区.堆内存区.全局/静态内存区.文字常量内存区及程序代码区5大分区: 下面使用日常开发中的编程实例,详细介绍一下这5个分区,以便大家能更深刻的理解这5大内存分区. 1.栈内存区 栈内存区是我们用的最多的分区,只要有函数的地方都会使用到这个分区.栈分区是用来存放函数参数及函数

  • python中字典和列表的相互嵌套问题详解

    目录 1.列表中存储字典: 1.列表中存储多个字典 2.访问列表中字典的值 3.遍历访问多个值 2.字典中存储列表 1.访问字典中的列表元素 2.访问字典中的值(字典中的值为列表) 3.字典中存储字典 1.字典中不能全部由字典元素组成,会报错. 2.字典中的值可由字典组成 4.容易出的小错误: 总结 首先明确: 1.访问字典中的元素:dict_name[key] / dict_name.get(key) 2.访问列表中的元素:list_name[索引] 1.列表中存储字典: 1.列表中存储多个字

  • python 字典和列表嵌套用法详解

    python中字典和列表的使用,在数据处理中应该是最常用的,这两个熟练后基本可以应付大部分场景了.不过网上的基础教程只告诉你列表.字典是什么,如何使用,很少做组合说明. 刚好工作中采集prometheus监控接口并做数据处理的时候,用了很多组合场景,列出几个做一些分享. 列表(List) 序列是Python中最基本的数据结构.序列中的每个元素都分配一个数字 - 它的位置,或索引,第一个索引是0,第二个索引是1,依此类推. 列表是最常用的Python数据类型,它可以作为一个方括号内的逗号分隔值出现

  • Python 列表和字典常踩坑即解决方案

    目录 一.关于列表 1.问题描述 2.解决方案 方案一 方案二 二.关于字典 1.问题描述 2.解决方案 结论 前言: 在Python中,如果我们想要在遍历一组数据的过程中,对这组数据进行修改,通常会出现许多问题,例如对列表进行上述操作时, 会忽略部分数据:遍历字典时,不能修改数据.本文针对这些问题,提出了多种解决方案. 一.关于列表 1.问题描述 在Python中,如果你试图在遍历一组数据的过程中,对其进行修改,这通常没什么问题. 例如: l = [3, 4, 56, 7, 10, 9, 6,

  • python中remove函数的踩坑记录

    摘要: 在python的使用过程中,难免会遇到要移除列表中对象的要求.这时可以使用remove函数. 对于python中的remove()函数,官方文档的解释是:Remove first occurrence of value.大意也就是移除列表中等于指定值的第一个匹配的元素. 语法 list.remove() 参数 obj 参数:从列表中删除的对象的索引 返回值 删除后不会返回值 常见用法: a = [1,2,3,4],a.remove(1),然后a就是[2,3,4]:对于a = [1,1,1

  • python列表,字典,元组简单用法示例

    本文实例讲述了python列表,字典,元组简单用法.分享给大家供大家参考,具体如下: 列表 #_*_ coding:utf-8 _*_ # 列表,定义在方括号的形式中,可以进行切片操作. #它没有固定类型的约束,即可以包含不同的数据类型. L=[1,'abc',2.3] print len(L) print '*'*40 L.append('mengtianwxs') print(L) print '*'*40 L.pop(0) print(L) print '*'*40 L.sort() pr

  • python 列表、字典和集合的添加和删除操作

    在python中,元组不可变,只能查询不能修改,列表.字典和集合的基本操作,各不相同,下面就来比较一下它们的添加和删除操作吧. 添加 一.列表 1."+"号 #两个数组相加,生成一个大数组 a = [1, 2, 3] b = [4, 5, 6] c = a + b print(c) #输出结果:[1, 2, 3, 4, 5, 6] 2.extend方法 #只接受列表参数并将参数的每个元素都添加到原有的列表中 a = [1, 2, 3] b = [4, 5, 6] a.extend(b)

  • 关于python scrapy中添加cookie踩坑记录

    问题发现: 前段时间项目中,为了防止被封号(提供的可用账号太少),对于能不登录就可以抓取的内容采用不带cookie的策略,只有必要的内容才带上cookie去访问. 本来想着很简单:在每个抛出来的Request的meta中带上一个标志位,通过在CookieMiddleware中查看这个标志位,决定是否是给这个Request是否装上Cookie. 实现的代码大致如下: class CookieMiddleware(object): """ 每次请求都随机从账号池中选择一个账号去访

  • 使用react-beautiful-dnd实现列表间拖拽踩坑

    为什么选用react-beautiful-dnd 相比于react-dnd,react-beautiful-dnd更适用于列表之间拖拽的场景,支持移动端,且较为容易上手. 基本使用方法 基本概念 DragDropContext:构建一个可以拖拽的范围 onDragStart:拖拽开始回调 onDragUpdate:拖拽中的回调 onDragEnd:拖拽结束时的回调 Droppable - 可以放置拖拽块的区域 Draggalbe - 可被拖拽的元素 使用方法 把你想能够拖放的代码放到DragDr

  • python 列表转为字典的两个小方法(小结)

    1.现在有两个列表,list1 = ['key1','key2','key3']和list2 = ['1','2','3'],把他们转为这样的字典:{'key1':'1','key2':'2','key3':'3'} >>>list1 = ['key1','key2','key3'] >>>list2 = ['1','2','3'] >>>dict(zip(list1,list2)) {'key1':'1','key2':'2','key3':'3'}

  • python 列表元素左右循环移动 的多种解决方案

    如下所示: #待处理列表 A= [1,2,3,4,5] #移动次数 a = 3 右移比较简单 for i in range(a): A.insert(0,A.pop()) 左移 for i in range(a): A.insert(len(A),A[0]) A.remove(A[0]) #左移 for i in range(a): b = A.pop(0) A.append(b) 列表双向队列 from collections import deque aa = deque(A) #正数表示向

  • 浅谈Python列表嵌套字典转化的问题

    在看视频教程的时候提到了[{'a' : 97}, {'b' : 98}, {'c' : 99}, {'d' : 100}, {'e' : 101}, ...........]形式的列表嵌套形式, 要求是将上述列表转换为{'a' : 97,'b' : 98,'c' : 99 ,'d' : 100,'e' : 101,.....}的字典形式 首先上述的a--->97, b--->98,.....意思是key为a到z的英文小写字母,value值为对应的ascii码, 那么一开始可以结合range()

  • pycharm+PyQt5+python最新开发环境配置(踩坑)

    安装工具: Pycharm 专业版2017.3 PyQT5 python3 测试工程文件及所需工具: 1.首先安装Pycharm,先前一篇介绍安装破解版的可以参考:https://www.jb51.net/softs/299378.html 2.新建一个空的python工程,找到setting安装第三方模块PyQT5,点加号,先安PyQT5,再安装pyqt5-tools,后面包含qtdesinger 3.以上模块都安完,设置扩展工具的参数找到setting->tools->external t

随机推荐