Python 简明教程 --- 14,Python 数据结构进阶

微信公众号:码农充电站pro
个人主页:https://codeshellme.github.io

如果你发现特殊情况太多,那很可能是用错算法了。
—— Carig Zerouni

目录

在这里插入图片描述

前几节我们介绍了Python 中四种数据结构的特性和基本用法,本节介绍与数据结构相关的高级特性。

  • 序列
  • 迭代器
  • 列表生成式
  • 生成器
  • 强制类型转换

1,序列

Python 序列是指,其中存放的元素是有序排列的,可用下标访问,字符串列表元组都是序列。

字典集合中的元素是无序排列的,因此一般不归在序列中。

Python 序列有如下特点:

  • 序列中的元素是不可变类型
  • 序列中的元素可用下标访问,下标可正可负
  • 可通过切片访问部分连续元素
  • 可进行相加相乘in 运算
  • 可通过for 循环遍历所有元素

可以使用collections 模块中的Sequence 类来查看一个对象是否是一个序列:

>>> isinstance('',collections.Sequence) # 字符串是序列
True
>>> isinstance([],collections.Sequence) # 列表是序列
True
>>> isinstance((),collections.Sequence) # 元组是序列
True
>>> isinstance({},collections.Sequence) # 字典不是序列
False
>>> isinstance(set(),collections.Sequence) # 集合不是序列
False

提示:

1,isinstance 函数用于查看一个对象属于某个类

2,在使用模块时,要先import 该模块

2,迭代器

可迭代类型

我们知道strlisttupledictset 都可用for 循环来遍历,这个遍历的过程就是一个迭代过程,这些类型都是可迭代类型。

可迭代的类型,都实现了__iter__ 方法,我们通过dir(可迭代对象),可以看到,可迭代对象的魔法方法中都有一个__iter__ 方法。

我们也可以通过collections 模块中的Iterable 类型来查看一个对象是不是可迭代对象:

>>> isinstance('',collections.Iterable)
True
>>> isinstance([],collections.Iterable)
True
>>> isinstance((),collections.Iterable)
True
>>> isinstance({},collections.Iterable)
True
>>> isinstance(set(),collections.Iterable)
True

迭代器

迭代器是一种可迭代的对象。

迭代器一定是可迭代的,可迭代的对象不一定是迭代器。

迭代器要实现两个魔法方法:__iter____next__

通过collections 模块中的Iterator 类型来查看这两个方法:

>>> dir(collections.Iterator)

判断一个对象是不是迭代器:

>>> isinstance('',collections.Iterator) # 字符串不是迭代器
False
>>> isinstance([],collections.Iterator) # 列表不是迭代器
False
>>> isinstance((),collections.Iterator) # 元组不是迭代器
False
>>> isinstance({},collections.Iterator) # 字典不是迭代器
False
>>> isinstance(set(),collections.Iterator) # 集合不是迭代器
False

迭代器通用函数

迭代器有一些通用函数,下面我们介绍一些常用的。

1.enumerate 函数

在Python3 中,enumerate 实际上是一个,可通过help(enumerate) 查看,也可以把它当做函数来使用。

其经常被用在for 循环中,即可遍历下标,又能遍历数据。

作用: 用于给一个可迭代的对象,添加下标
原型: enumerate(iterable[,start]) -> iterator
参数 iterable: 一个可迭代的对象
参数 start: 下标起始位置
返回值: 一个enumerate 对象,同时也是一个迭代器

示例:

>>> l = enumerate(['a','c','b']) # 参数是一个列表
>>> type(l)
<class 'enumerate'>
>>> isinstance(l,collections.Iterator) # 是一个迭代器
True
>>> for index,item in l:           # for 循环遍历,能遍历出下标
...     print(index,item)
... 
0 a
1 c
2 b

2.iter 函数

作用:将一个可迭代的序列iterable 转换成迭代器
原型:iter(iterable) -> iterator
参数:iterable 是一个可迭代的序列
返回值:一个迭代器

示例:

>>> iter('123')            # 参数是字符串
<str_iterator object at 0x7fcb7dd320b8>     # str 迭代器
>>> iter([1,2,3])        # 参数是列表
<list_iterator object at 0x7fcb7dd4a0b8>    # list 迭代器
>>> iter((1,3))        # 参数是元组
<tuple_iterator object at 0x7fcb7dd4a0b8>   # tuple 迭代器
>>> iter(set([1,3]))   # 参数是集合
<set_iterator object at 0x7fcb7d2c5e10>     # set 迭代器
>>> iter({'a':1,'b':2})   # 参数是字典
<dict_keyiterator object at 0x7fcb7f467098> # dict 迭代器

3.next 函数

作用:返回迭代器的下一个元素
原型:next(iterator[,default]) -> item
参数 iterator:是一个迭代器类型
参数 default:任意类型数据,可省
返回值

迭代器中有元素时:返回迭代器中的下一个元素
迭代器中没有元素没有default 参数时:抛出StopIteration 异常
迭代器中没有元素有default 参数时:返回default

示例:

>>> i = iter([1,3,5])  # i 是一个迭代器
>>> next(i)              # 返回 1
1
>>> next(i)              # 返回 3
3
>>> next(i)              # 返回 5
5
>>> next(i)              # i 中没有元素,抛出异常
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
StopIteration
>>> 
>>> next(i,7)           # i 中没有元素,返回第二个参数 7
7

4.len 函数

作用:用于计算一个对象obj中的元素的个数
原型:len(obj,/)
参数:一般obj 是一个可迭代类型对象,实际上,只要实现了__len__ 方法的对象,都可以使用该函数
返回值:一个整数

示例:

>>> len('abc')
3
>>> len([1,3])
3

5.max 函数

作用:返回可迭代对象iterable 中的最大元素
原型:max(iterable)
参数iterable 是一个可迭代的对象,并且iterable 中的元素可比较
返回值:最大值

示例:

>>> max([1,2])
2
>>> max([1,3])
3
>>> max('b','a')
'b'
>>> max('abc')
'c'
>>> max(1,'a')     # 整数与字符串不是同类型,不可比较
Traceback (most recent call last):
  File "<stdin>",in <module>
TypeError: '>' not supported between instances of 'str' and 'int'

6.min 函数

作用:返回可迭代对象iterable 中的最小元素
原型:min(iterable)
参数iterable 是一个可迭代的对象,并且iterable 中的元素可比较
返回值:最小值

示例:

>>> min([1,2])
1
>>> min([2,3])
2
>>> min('abc')
'a'
>>> min('b','c')
'b'
>>> min('b',2)  # 整数与字符串不是同类型,不可比较
Traceback (most recent call last):
  File "<stdin>",in <module>
TypeError: '<' not supported between instances of 'int' and 'str'

7.sum 函数

作用:计算可迭代对象iterable 中的数据之和,最后在加上 start
原型:sum(iterable,start=0,/)
参数iterable 是一个可迭代对象,其中的元素是数字类型
返回值:所有元素之和

示例:

>>> sum([1,3])     # 计算 1,2,3 之和
6
>>> sum([1,3],5)  # 计算 1,2,3 之和,再加上 5
11

8.reversed 函数

reversed 实际上是一个类,可用help(reversed) 查看。

作用:将一个序列sequence 反转
原型:reversed(sequence)
参数sequence 是一个序列类型
返回值:一个reversed 对象,该对象也是一个迭代器,可被迭代

示例:

>>> r = reversed('abcde')
>>> r                                    # 一个 reversed 对象
<reversed object at 0x7fcb79970518>
>>> isinstance(r,collections.Iterator)  # 也是一个迭代器
True
>>> [i for i in r]                  # 转换成列表,查看其中的元素
['e','d','b','a']
>>>
>>> r = reversed([1,5,7])
>>> [i for i in r]
[7,1]

3,列表生成式

列表生成式,又叫列表推导式,用于从一个可迭代对象生成一个列表,它是一种代码简写形式,其优点是代码简洁优雅。

比如,我们有一个列表 [1,5],想求其中每个元素的平方,再将结果放入列表中,最终的结果是[1,9,25]

如果是一般的方式,我们写出来的代码是这样的:

l = [1,5]

l2 = []
for i in l:
    item = i * i 
    l2.append(item)

print(l2)   

如果用列表生成式的方式,代码是这样的:

l = [1,5]

l2 = [i * i for i in l]

print(l2)

可以看到列表生成式比普通的形式要简洁许多。

列表生成式语法

最简单的列表生成式的语法,就像上面的代码一样:

在这里插入图片描述

列表生成式由三部分组成:

  • 列表符号:中括号[]
  • 表达式:用于生成新列表中的每个元素,一般与item 有关,也可无关
  • for 循环:用于迭代原始可迭代对象

列表生成式中的if 判断

列表生成式中也可以有if 判断,当判断条件成立时,才会执行表达式,并将该表达式的结果append 到新的列表中。

这里的if 判断没有else 部分,判断条件一般与item 有关。

如下:

在这里插入图片描述

示例:

l = [1,5]

# 只有当 l 中的元素大于 1 时,才算平方
l2 = [i * i for i in l if i > 1]

print(l2)

range 函数

Python2.x 中range 是一个函数

Python3.x 中,range 是一个,可用help(range) 查看其手册。

>>> range
<class 'range'>

下面介绍Python3.xrange 的用法,有两种参数形式:

作用:生成一个从startstop 的,步长为step 的,可迭代的整数序列,该序列包含start,不包含stop,即遵循左开右闭原则
原型

range(stop) -> range object
range(start,stop[,step]) -> range object

参数

当只有stop 参数时,该序列从0 开始到stop,步长为1
当有startstop 参数时,该序列从start 开始到stop,步长为1
当有step 参数时,步长为step

返回值:一个range 对象

示例:

>>> range(5)
range(0,5)
>>> range(1,5)
range(1,2)
range(1,2)

range 对象是一个序列,而不是一个迭代器:

>>> isinstance(range(5),collections.Sequence)
True
>>> isinstance(range(5),collections.Iterator)
False

可以使用列表生成式来查看range 中的内容:

>>> [i for i in range(5)]       # 从 0 到 5
[0,1,4]
>>> [i for i in range(1,5)]    # 从 1 到 5
[1,2)] # 步长为 2
[1,3]

4,生成器

生成器也是一个迭代器。生成器跟列表有点像,但优点是比列表节省内存

对于列表,Python 会为列表中的每个元素都分配实实在在的内存空间,如果列表中的元素很多,那么列表将消耗大量内存。

而对于生成器,Python 并不会为其中的每个元素都分配内存。

生成器记录的是一种算法,是如何生成数据的算法,在每次用到数据时,才会去生成数据,而不会一开始就将所有的数据准备好。

因此,对于相同的功能,生成器列表都能完成,而生成器可以节省大量的内存。

创建生成器有两种方式:

  • 列表生成式中的中括号[]改为小括号()
  • 在函数中使用yield 关键字

使用列表生成式

如下代码可以生成一个列表:

>>> [i for i in range(5)]
[0,4]

将中括号[] 改为小括号(),就是一个生成器:

>>> l = (i for i in range(5))
>>> l
<generator object <genexpr> at 0x7f3433d2d9e8>
>>> type(l)
<class 'generator'>
>>> isinstance(l,collections.Iterator) # 生成器也是一个迭代器
True

其中的generator 就是生成器的意思,它也是一个

使用yield 关键字

比如,我们想计算列表[1,5] 中每个元素的平方,使用yield 关键字,代码如下:

#! /usr/bin/env python3

def test():
    print('test...')
    l = [1,5]

    for i in l:
        tmp = i * i 
        print('yield tmp:%s' % tmp)
        yield tmp 

t = test()
print(t)       # <generator object test at 0x7fde1cdaa3b8> 
print(type(t)) # <class'generator'>

注意,我们定义了一个函数,这里我们只是为了演示如何使用yield 来创建生成器,而不用过多关注如何定义函数。

函数的概念我们会在后续章节详细介绍。

执行以上代码,输出如下:

<generator object test at 0x7fde1cdaa3b8> 
<class'generator'>

你会发现,字符串test...并没有被打印出来。

你可能会有疑问,既然代码t = test() 已经执行了,那整个test() 函数中的代码都应该执行完了才对,那字符串test... 怎么会没有打印呢?

那是因为,生成器中代码的执行是惰性的。当执行t = test() 这行代码时,test() 函数并没有被执行。

前边我们说过,生成器记录的是一个算法,而不是真正的数据,数据只有当使用到的时候,才会去生成。

所以,变量 t 中只是一个算法,而没有数据。

因为,生成器也是一个迭代器,所以生成器可以使用next() 函数来访问其中的数据:

i = next(t)
print('i value is',i) 

执行上面这行代码后,程序会输出:

test...
yield tmp:1
i value is 1

字符串test... 被打印,说明test() 执行了。

当代码执行到yield 时,变量i 会接收到yield 返回的数据,此时,代码会从yield 处跳出test() 函数。

如果接下来,不再遍历变量t 中的数据,那么整个代码就执行结束了。

如果我们再次执行代码:

j = next(t)
print('j value is',j) 

程序会输出:

yield tmp:9
j value is 9

可见代码会在上次yield 的地方,再次向下执行。

我们再次执行代码:

k = next(t)
print('k value is',k) 

程序会输出:

yield tmp:25
k value is 25

t 中的元素被遍历完后,如果再次执行next(t),则会抛出StopIteration 异常。

使用next() 函数来遍历生成器中的所有元素是很麻烦的,我们可以像遍历列表一样,用for 循环来遍历生成器中的元素:

for i in t:
    print(i) 

输出如下:

test...
yield tmp:1
1
yield tmp:9
9
yield tmp:25
25

整个遍历过程中,字符串test... 只被输出了一次,并没有被输出三次。

说明当代码执行到yield 时,并没有从函数test() 中返回,代码只是暂停在了yield 处,等下次需要数据时,会接着从上次的yield 处接着执行。

生成器比列表节省内存

如果我们想生成一个从09999 的数字序列,用列表的话,是这样的:

>>> l = [i for i in range(10000)]
>>> sys.getsizeof(l)  # 内存占用 87624 字节
87624

sys 模块的getsizeof 方法可以查看一个对象的大小,单位是字节

用生成器来实现的话,是这样的:

>>> l = (i for i in range(10000))
>>> sys.getsizeof(l)  # 内存占用 88 字节
88

可以看到09999 这样的整数序列,使用列表的话,占用 87624 字节;使用生成器的话,只占用 88 字节

5,强制类型转换

我们已经知道了,Python3 中的strlisttupledictset 都是一个类:

>>> type('')
<class 'str'>
>>> type([])
<class 'list'>
>>> type(())
<class 'tuple'>
>>> type({})
<class 'dict'>
>>> type(set())
<class 'set'>

每个类都有构造方法,这些构造方法可以将其它类型的数据,转换成该类型数据,我们也可以将这种转换称为强制类型转换

提示:

构造方法是一个的初始化方法,就是用什么样的数据去构造一个特定类的对象。

当介绍到类与对象时,我们会详细介绍。

str强制转换

作用: 将其它类型数据转换成字符串
原型: str(object='') -> str
参数: 任意类型数据
返回值: 字符串

示例:

>>> str(1)        # 将数字转换成字符串
'1'
>>> str([1,2])   # 将列表转换成字符串
'[1,2]'
>>> str((1,2))   # 将元组转换成字符串
'(1,2)'

list强制转换

作用: 将一个可迭代类型转成列表
原型: list(iterable) -> list
参数: 任意可迭代类型数据
返回值: 列表

示例:

>>> list((1,2))   # 将一个元组转成列表
[1,2]
>>> list(range(3)) # 将一个 range 对象转成列表
[0,2]

tuple强制转换

作用: 将一个可迭代类型转成元组
原型: tuple(iterable) -> tuple
参数: 任意可迭代类型数据
返回值: 元组

示例:

>>> tuple([1,2])    # 将一个列表转成元组
(1,2)
>>> tuple(range(3))  # 将一个 range 对象转成元组
(0,2)

dict强制转换

作用: 将一个可迭代类型数据转成字典
原型: dict(iterable) -> dict
参数: iterable 是一个可迭代对象,并且该对象中的元素是元组
返回值: 字典

示例:

>>> t = ((1,2),(2,3))  # t 是一个元组,其中的元素也是元组
>>> dict(t)
{1: 2,2: 3}
>>> 
>>> l = [(1,3)] # l 是一个列表,其中的元素是元组
>>> dict(l)
{1: 2,2: 3}

set强制转换

作用: 将一个可迭代类型数据转成集合
原型: set(iterable) -> set
参数: 一个可迭代对象
返回值: 集合

其实,我们在介绍集合时,都是用的这种方式来声明的集合,示例:

>>> set('abc')      # 将一个字符串转成集合
{'b','a'}
>>> set([0,1])     # 将一个列表转成集合
{0,1}
>>> set((0,1))     # 将一个元组转成集合
{0,1}

(完。)

推荐阅读:

Python 简明教程 --- 9,Python 编码

Python 简明教程 --- 10,Python 列表

Python 简明教程 --- 11,Python 元组

Python 简明教程 --- 12,Python 字典

Python 简明教程 --- 13,Python 集合

欢迎关注作者公众号,获取更多技术干货。

码农充电站pro

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用OpenCV实现视频去抖 整体步骤: 设置输入输出视频 寻找帧之间的移动:使用opencv的特征检测器,检测前一帧的特征,并使用Lucas-Kanade光流算法在下一帧跟踪这些特征,根据两组点,将前一个坐标系映射到当前坐标系完成刚性(欧几里得)变换,最后使用数组纪录帧之间的运动。 计算帧之间的平
前言 对中文标题使用余弦相似度算法和编辑距离相似度分析进行相似度分析。 准备数据集part1 本次使用的数据集来源于前几年的硕士学位论文,可根据实际需要更换。结构如下所示: 学位论文题名 基于卷积神经网络的人脸识别研究 P2P流媒体视频点播系统设计和研究 校园网安全体系的设计与实现 无线传感器网络中
前言 之前尝试写过一个爬虫,那时对网页请求还不够熟练,用的原理是:爬取整个html文件,然后根据标签页筛选有效信息。 现在看来这种方式无疑是吃力不讨好,因此现在重新写了一个爬取天气的程序。 准备工作 网上能轻松找到的是 101010100 北京这种编号,而查看中国气象局URL,他们使用的是北京545
前言 本文使用Python实现了PCA算法,并使用ORL人脸数据集进行了测试并输出特征脸,简单实现了人脸识别的功能。 1. 准备 ORL人脸数据集共包含40个不同人的400张图像,是在1992年4月至1994年4月期间由英国剑桥的Olivetti研究实验室创建。此数据集包含40个类,每个类含10张图
前言 使用opencv对图像进行操作,要求:(1)定位银行票据的四条边,然后旋正。(2)根据版面分析,分割出小写金额区域。 图像校正 首先是对图像的校正 读取图片 对图片二值化 进行边缘检测 对边缘的进行霍夫曼变换 将变换结果从极坐标空间投影到笛卡尔坐标得到倾斜角 根据倾斜角对主体校正 import
天气预报API 功能 从中国天气网抓取数据返回1-7天的天气数据,包括: 日期 天气 温度 风力 风向 def get_weather(city): 入参: 城市名,type为字符串,如西安、北京,因为数据引用中国气象网,因此只支持中国城市 返回: 1、列表,包括1-7的天气数据,每一天的分别为一个
数据来源:House Prices - Advanced Regression Techniques 参考文献: Comprehensive data exploration with Python 1. 导入数据 import pandas as pd import warnings warnin
同步和异步 同步和异步是指程序的执行方式。在同步执行中,程序会按顺序一个接一个地执行任务,直到当前任务完成。而在异步执行中,程序会在等待当前任务完成的同时,执行其他任务。 同步执行意味着程序会阻塞,等待任务完成,而异步执行则意味着程序不会阻塞,可以同时执行多个任务。 同步和异步的选择取决于你的程序需
实现代码 import time import pydirectinput import keyboard if __name__ == &#39;__main__&#39;: revolve = False while True: time.sleep(0.1) if keyboard.is_pr
本文从多个角度分析了vi编辑器保存退出命令。我们介绍了保存和退出vi编辑器的命令,以及如何撤销更改、移动光标、查找和替换文本等实用命令。希望这些技巧能帮助你更好地使用vi编辑器。
Python中的回车和换行是计算机中文本处理中的两个重要概念,它们在代码编写中扮演着非常重要的角色。本文从多个角度分析了Python中的回车和换行,包括回车和换行的概念、使用方法、使用场景和注意事项。通过本文的介绍,读者可以更好地理解和掌握Python中的回车和换行,从而编写出更加高效和规范的Python代码。
SQL Server启动不了错误1067是一种比较常见的故障,主要原因是数据库服务启动失败、权限不足和数据库文件损坏等。要解决这个问题,我们需要检查服务日志、重启服务器、检查文件权限和恢复数据库文件等。在日常的数据库运维工作中,我们应该时刻关注数据库的运行状况,及时发现并解决问题,以确保数据库的正常运行。
信息模块是一种可重复使用的、可编程的、可扩展的、可维护的、可测试的、可重构的软件组件。信息模块的端接需要从接口设计、数据格式、消息传递、函数调用等方面进行考虑。信息模块的端接需要满足高内聚、低耦合的原则,以保证系统的可扩展性和可维护性。
本文从电脑配置、PyCharm版本、Java版本、配置文件以及程序冲突等多个角度分析了Win10启动不了PyCharm的可能原因,并提供了解决方法。
本文主要从多个角度分析了安装SQL Server 2012时可能出现的错误,并提供了解决方法。
Pycharm是一款非常优秀的Python集成开发环境,它可以让Python开发者更加高效地进行代码编写、调试和测试。在Pycharm中设置解释器非常简单,我们可以通过创建新项目、修改项目解释器、设置全局解释器等多种方式进行设置。
Python中有多种方法可以将字符串转换为整数,包括使用int()函数、try-except语句、正则表达式、map()函数、ord()函数和reduce()函数。在实际应用中,应根据具体情况选择最合适的方法。
本文介绍了导入CSV文件的多种方法,包括使用Excel、Python和R等工具。同时,还介绍了导入CSV文件时需要注意的一些细节和问题。CSV文件是数据处理和分析中不可或缺的一部分,希望本文能够对读者有所帮助。
mongodb是一种新型的数据库,它采用了面向文档的数据模型,具有灵活性、高性能和高可用性等优势。但是,mongodb也存在数据结构混乱、安全性和学习成本高等问题。
当Python运行不了时,我们应该从代码、Python环境、操作系统和硬件设备等多个角度来排查问题,并采取相应的解决措施。