python遍历列表遇到的问题以及处理方法

一、前言

本节主要讲解问题如下:
1.用python代码实现一个range函数
2.python遍历列表时删除元素的错误做法
3.python遍历列表时删除元素的正确做法

二、python代码实现一个range函数

相信接触过python语言的我们,肯定都会经常使用range函数,那么这个range函数内部到底是怎么实现的呢?

下面我来仿造python的内置range函数来实现一个简单的range函数,代码如下:



class Mrange(object):
    def __init__(self,start,stop=None,step=None):
        #模拟range从0开始的行为
        if stop is None:
            self.start = 0
            self.stop = start -1
        else:
            self.start = start
            self.stop = stop -1

        self.step = step

        # 保留原始参数(打印对象的时候要使用)
        self.origin_start = self.start
        self.origin_stop = self.stop + 1
        self.origin_step = self.step

    def __repr__(self):
        """

        :return:显示表现(打印print时触发这个函数)
        """
        print('触发__repr__方法')
        if self.origin_step:
            result = '{}({},{},{})'.format(
                self.__class__.__name__,#获取类名
                self.origin_start,
                self.origin_stop,
                self.origin_step
            )
        else:
            result = '{}({},{})'.format(
                self.__class__.__name__,
                self.origin_start,
                self.origin_stop,
            )
        return result

    def __iter__(self):
        return self

    def __next__(self):
        """
        :return: 返回当前数字
        """
        result = self.start

        #步长取默认值1
        if self.step is None:
            if self.start <= self.stop:
                self.start += 1
            else:
                raise StopIteration  #迭代器迭代完成会引发StopIteration异常
        #按给的步长默认值1
        else:
            if self.start <= self.stop:
                self.start += self.step
            else:
                raise StopIteration  # 迭代器完成会引发StopIteration异常
        return result

mrange = Mrange(2,10,1)
print(mrange)

for i in mrange:  #因为for循环内部有异常处理机制,所以当迭代器迭代完成并不会抛出异常
    print(i)


上述代码的具体逻辑不再说明,这里主要说明几个函数的触发时机:
__repr__函数:当执行print打印这个类的对象时触发
__iter__函数:这里返回的是一个迭代器对象(不理解的可以去看可迭代对象和迭代器对象的区别),这个函数一般在for循环遍历可迭代对象时触发
__next__函数:一般在for循环遍历时触发

以上,就实现了一个简单的步长只能为正数的range函数

为什么这里要说range呢?因为下面要用到,请看下面

三、python遍历列表时删除元素的错误做法

错误方式1:

a = [1,2,3,4,5,6,7,8]
for i in a:
    if i > 5:
        pass
    else:
        a.remove(i)
print(a)
# 打印结果  [2, 4, 6, 7, 8]
#错误原因:因为遍历的是原列表,每次删除都会对原列表造成长度减1,
#但是for遍历的下标还是按照原来的下标来遍历,所以会造成元素跳过

如下图:
在这里插入图片描述

错误方式2

a = [1,2,3,4,5,6,7,8]
for i in range(len(a)):
    print(len(a),i)
    if a[i]>5:
        pass
    else:
        a.remove(a[i])
print(a)
#报错:IndexError: list index out of range
从这里的索引越界报错可以看出,range(len(a))确定之后就算a的长度变化,这里的值也是固定的了

这里错误的原因是:遍历的时候按照原列表的长度来遍历,可是中间执行过程中原列表的长度变小,所以,产生了下标越界的问题

四、python遍历列表时删除元素的正确做法

方法一: filter方法实现

a = [1,2,3,4,5,6,7,8]
s = filter(lambda x:x>5,a)
for i in s:
    print(i)

方法二: 列表生成式实现

a = [1,2,3,4,5,6,7,8]
b = [i for i in a if i>5]
print(b)

方法三: 倒序删除

a = [1,2,3,4,5,6,7,8]
for i in range(len(a)-1,-1,-1):
    if a[i] > 5:
        pass
    else:
        a.remove(a[i])
print(a)
因为列表总是“向前移动”,所以可以倒序遍历,即使后面的元素被修改了,还没有被遍历的元素和其坐标还是保持不变的

这里,本人画图水平不高,可以自己试试画图实现一次次遍历,就会发现规律

参考文章

Python遍历是指通过循环结构逐一遍历数据集合中的每个元素并对其进行处理的过程。常见的遍历操作包括对列表、元组、字典等容器类型的迭代。 ### 遍历列表 最简单的遍历方法是使用`for...in`语句: ```python fruits = ['apple', 'banana', 'cherry'] for fruit in fruits: print(fruit) ``` 这段代码会依次打印出每一种水果名称。 #### 获取索引的方式 如果需要同时获取下标和对应的值,可以结合内置函数`enumerate()`来完成: ```python fruits = ['apple', 'banana', 'cherry'] for index, value in enumerate(fruits): print(f"Index {index}: Value {value}") ``` 上述代码将输出每一项的序号及其对应的内容。 ### 字典遍历 对于字典来说,默认情况下直接遍历的是键(Key),也可以指定遍历值或键值对: - **仅遍历键**: ```python person_info = {"name": "Alice", "age": 30} for key in person_info: print(key) # 输出"name","age" ``` - **遍历所有值**: ```python for val in person_info.values(): print(val) # 输出"Alice",30 ``` - **遍历键值对**: 使用`.items()`,这能更方便地访问到key-value组合 ```python for k,v in person_info.items(): print(k,'->',v) ``` 此外,在某些特定场景里我们可能会遇到嵌套的数据结构,这时就需要递归或者其他高级技巧来进行更深一层级别的遍历了。 最后提醒一点,当尝试修改正在被迭代的对象时需格外小心,因为这样做可能导致意外的结果甚至抛异常!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值