当前位置: 首页 > news >正文

Python的迭代器(Iterator)介绍以及实现多次使用

        在 Python 中,我们希望能够对迭代器(Iterator)多次使用。

一、问题描述

        有一个数据文件,tourist_data.csv,数据结构如下:

日期九寨沟张家界香港东部华侨城上海迪士尼
2017/1/1301717328
2017/1/21221839
2017/1/3142215132
2017/1/462913715
2017/1/531155310
2017/1/6262317625
2017/1/791812728
2017/1/891912415
2017/1/92224111014
2017/1/103296320
2017/1/11101916326
2017/1/12171717731
2017/1/13212512106
2017/1/14172715132

        现在想统计每一个旅游景点的游客访问量,代码如下:

import csv
def getTotalTourist(place):
    total = 0
    for dayTourist in place:
        total += dayTourist
    return total
data_file = open('C:/Users/Admin/Desktop/chapter3/tourist_data.csv','r')
all_data = csv.reader(data_file)

jzg_data = [row[1] for row in all_data]  #第二列
#print(jzg_data)
jzg_data_str = jzg_data[1:]
jzg_data = list( map(int, jzg_data_str) )
#print(jzg_data)
jzg_total = getTotalTourist(jzg_data)
print("这段时期到九寨沟旅游的总人数是:",jzg_total)

zjj_data = [row[2] for row in all_data]   #第三列
#print(zjj_data)
zjj_data_str = zjj_data[1:]
zjj_data = list( map(int, zjj_data_str) )
#print(zjj_data)
zjj_total = getTotalTourist(zjj_data)
print("这段时期到张家界旅游的总人数是:",zjj_total)

dbhqc_data = [row[3] for row in all_data]   #第四列
#print(dbhqc_data)
dbhqc_data_str = dbhqc_data[1:]
dbhqc_data = list( map(int, dbhqc_data_str) )
#print(dbhqc_data)
dbhqc_total = getTotalTourist(dbhqc_data)
print("这段时期到东部华侨城旅游的总人数是:",dbhqc_total)

shdisney_data = [row[4] for row in all_data]   #第五列
#print(shdisney_data)
shdisney_data_str = shdisney_data[1:]
shdisney_data = list( map(int, shdisney_data_str) )
#print(shdisney_data)
shdisney_total = getTotalTourist(shdisney_data)
print("这段时期到上海迪士尼旅游的总人数是:",shdisney_total)

data_file.close()

        如上代码,得到的结果如下:

        以上代码文件读取没有问题,但是只能输出第一个jzg_total,即九寨沟的旅游人数,其他几个旅游点输出都是0,这是什么问题呢?

二、问题所在

        问题出在 csv.reader 的使用上。csv.reader 返回的是一个迭代器,一旦迭代器被遍历一次后,它会被耗尽,无法再次使用。因此,当你第一次从 all_data 中提取 jzg_data 时,all_data 已经被完全迭代,后续再尝试从 all_data 中提取其他列数据时,迭代器已经为空,导致 zjj_datadbhqc_datashdisney_data 都是空列表,进而导致它们的总数为 0。

三、解决方法

        需要在第一次读取 all_data 时,将其存储为一个列表,这样就可以多次访问数据。以下是修改后的代码:

import csv

def getTotalTourist(place):
    total = 0
    for dayTourist in place:
        total += dayTourist
    return total

data_file = open('C:/Users/Admin/Desktop/chapter3/tourist_data.csv', 'r')
all_data = list(csv.reader(data_file))  # 将 csv.reader 的结果存储为列表

# 提取九寨沟的数据(第二列)
jzg_data = [int(row[1]) for row in all_data[1:]]  # 直接转换为整数
jzg_total = getTotalTourist(jzg_data)
print("这段时期到九寨沟旅游的总人数是:", jzg_total)

# 提取张家界的数据(第三列)
zjj_data = [int(row[2]) for row in all_data[1:]]  # 直接转换为整数
zjj_total = getTotalTourist(zjj_data)
print("这段时期到张家界旅游的总人数是:", zjj_total)

# 提取东部华侨城的数据(第四列)
dbhqc_data = [int(row[3]) for row in all_data[1:]]  # 直接转换为整数
dbhqc_total = getTotalTourist(dbhqc_data)
print("这段时期到东部华侨城旅游的总人数是:", dbhqc_total)

# 提取上海迪士尼的数据(第五列)
shdisney_data = [int(row[4]) for row in all_data[1:]]  # 直接转换为整数
shdisney_total = getTotalTourist(shdisney_data)
print("这段时期到上海迪士尼旅游的总人数是:", shdisney_total)

data_file.close()

修改点说明

  1. csv.reader 的结果存储为列表

    all_data = list(csv.reader(data_file))

    这样可以多次访问 all_data,而不会因为迭代器耗尽而无法读取数据。

  2. 直接在列表解析中转换为整数

    jzg_data = [int(row[1]) for row in all_data[1:]]

    这样可以避免额外的字符串到整数的转换步骤,代码更简洁。

  3. 跳过表头: 使用 all_data[1:] 跳过表头行,确保只处理数据行。

        通过这些修改,代码可以正确读取并处理所有列的数据,输出每个景区的总人数。

实现的效果

四、迭代器(Iterator)介绍

        在 Python 中,迭代器(Iterator)是一种容器对象,它实现了迭代器协议(Iterator Protocol),允许用户通过循环或迭代的方式逐个访问容器中的元素,而无需暴露容器的底层实现细节。迭代器是 Python 中实现迭代功能的核心机制,广泛应用于各种数据结构和场景。

1. 迭代器协议

        迭代器协议包括两个方法:

  • __iter__():返回迭代器对象本身。这个方法使得对象可以被用于 for 循环或其他需要迭代的场景。

  • __next__():返回迭代器的下一个元素。如果迭代器已经到达末尾,没有更多元素可供返回,则抛出 StopIteration 异常。

2. 创建迭代器

        在 Python 中,可以通过以下几种方式创建迭代器:

2.1 使用内置的可迭代对象

        许多内置数据类型(如列表、元组、字典、集合、字符串等)都支持迭代器协议,可以直接使用 iter() 函数将其转换为迭代器。例如:

my_list = [1, 2, 3, 4]
my_iterator = iter(my_list)

print(next(my_iterator))  # 输出 1
print(next(my_iterator))  # 输出 2
print(next(my_iterator))  # 输出 3
print(next(my_iterator))  # 输出 4
# print(next(my_iterator))  # 抛出 StopIteration 异常
2.2 自定义迭代器

        可以通过定义一个类并实现 __iter__()__next__() 方法来创建自定义迭代器。例如:

class MyIterator:
    def __init__(self, max_value):
        self.max_value = max_value
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.max_value:
            value = self.current
            self.current += 1
            return value
        else:
            raise StopIteration

# 使用自定义迭代器
my_iterator = MyIterator(5)
for value in my_iterator:
    print(value)  # 输出 0, 1, 2, 3, 4
2.3 使用生成器

        生成器是一种特殊的迭代器,通过 yield 关键字实现。生成器函数在每次调用时会返回一个值,并在下次调用时从上次返回的位置继续执行。生成器是实现迭代器的简洁方式。例如:

def my_generator(max_value):
    current = 0
    while current < max_value:
        yield current
        current += 1

# 使用生成器
for value in my_generator(5):
    print(value)  # 输出 0, 1, 2, 3, 4

3. 迭代器的特点

  • 惰性计算:迭代器不会一次性加载所有数据,而是按需生成数据,节省内存。

  • 一次性使用:迭代器在被完全迭代后,会耗尽,无法再次使用。如果需要重新迭代,需要重新创建迭代器。

  • 支持无限序列:生成器可以用于生成无限序列,因为它们不需要预先存储所有数据。例如:

    def infinite_generator():
        current = 0
        while True:
            yield current
            current += 1
    
    # 使用无限生成器(需要小心避免无限循环)
    gen = infinite_generator()
    for _ in range(10):
        print(next(gen))  # 输出 0, 1, 2, ..., 9

4. 迭代器的应用场景

  • 循环遍历for 循环会自动调用 iter()next() 方法来迭代对象。

  • 函数式编程:许多函数式编程工具(如 map()filter()zip() 等)返回迭代器,便于高效处理数据。

  • 文件读取:文件对象本身是一个迭代器,可以逐行读取文件内容,节省内存。

    with open('file.txt', 'r') as file:
        for line in file:
            print(line.strip())

5. 迭代器与可迭代对象的区别

  • 可迭代对象(Iterable):实现了 __iter__() 方法或 __getitem__() 方法的对象,可以通过 iter() 转换为迭代器。例如:列表、元组、字典、集合、字符串等。

  • 迭代器(Iterator):实现了 __iter__()__next__() 方法的对象,可以直接用于迭代。

6. 总结

        迭代器是 Python 中实现迭代功能的核心机制具有惰性计算、节省内存、支持无限序列等特点。通过内置的可迭代对象、自定义迭代器或生成器,可以灵活地实现各种迭代需求。理解迭代器的原理和使用方法,可以帮助你更高效地处理数据和编写代码。

相关文章:

  • SVTAV1热点函数-svt_ext_all_sad_calculation_8x8_16x16_avx2
  • pip 安装某个包之后,Jupyter Lab仍旧显示包冲突;例如:Numba needs NumPy 2.1 or less. Got NumPy 2.2.
  • 热血传奇2超高清重置UI素材
  • Java并发编程
  • SAP-ABAP:OData 协议深度解析:架构、实践与最佳应用
  • 重学Java基础篇—什么是快速失败(fail-fast)和安全失败(fail-safe)?
  • 【Pandas】pandas Series to_xarray
  • 类和对象—继承(1)
  • 什么是真理?以及人工智能对真理标准的挑战
  • c++ 日志框架G3log介绍及在嵌入式Linux上的移植(交叉编译)
  • 学习笔记—数据结构—二叉树(链式)
  • 网关及路由
  • mapbox V3 新特性,添加三维球鹰眼图控件
  • 冗余技术:堆叠技术+链路聚合
  • 循环神经网络(RNN)
  • unity一个图片的物体,会有透明的效果
  • DMA 之FIFO的作用
  • CMake入门及生成windows下的项目示例讲解
  • RGB-D综述
  • Mysql5.7的my.cnf配置文件
  • 安徽网站建设公司/佛山本地网站建设
  • 柏乡网站建设/seo网站优化建议
  • 做设计赚钱的网站/企业建站 平台
  • 域名服务器是什么意思/关系网站优化公司
  • ppt模板下载的网站有哪些/sem工资
  • 风铃微网站怎么做/深圳网络营销推广