Python基础-5 数据结构

数据结构

简单介绍Python中常用的几种数据结构。

1. 列表 list

列表类似于其它编程语言里的可变数组。

标准库参考:列表是可变序列,通常用于存放同类项目。

1.1 列表的创建

  • 使用方括号创建空列表:[]

  • 使用方括号,里面的项用,隔开:[a,b,c]

  • 使用列表推导式:[x for x in iterable]

  • 使用构造器: list()或list(iterable)

构造器会返回一个列表,其中的项与iterable中的项值和顺序都相同。iterable是一个可迭代对象。

1.2 列表的操作

列表是可变序列,因此它支持通用序列操作可变序列操作

通用序列操作:支持判断,求值等操作,但不可修改序列内容。

通用序列操作.png

可变序列操作:

除了通用序列操作,还支持对序列元素赋值、删除等操作。


可变序列操作.png

列表额外方法

``sort(*, key=None, reverse=False)

就地排序列表中的元素。key是有一个参数的函数,用来生成用于比较的键;reverse是True或False,表示是否反转。*用来限定后面的参数仅能通过关键字方式传递。

lst1 = [1,2,3,7,3,4]
lst1.sort()
print(lst1)

key参数很适合用lambda表达式:

scores = [('a', 99), ('b', 66), ('c', 77), ('d', 88)]
scores.sort(key=lambda x: -x[1])
print(scores)

使用列表实现堆栈、队列

堆栈是一种后进先出的数据结构。可以将堆栈想象成一口井。

(堆栈:进的顺序是1,2,3,4。出的顺序是4,3,2,1。)

使用列表实现堆栈非常容易,用append()模拟进栈,pop()模拟出栈。

stack = [1, 2, 3]
stack.append(4)
stack.append(5)
print(stack)

stack.pop()
print(stack)

stack.pop()
stack.pop()

print(stack)

队列是一种先进先出的数据结构。相当于排队。

队列

(队列:进的顺序1,2,3,4.出的顺序也是1,2,3,4)

可以使用append()模拟入队,pop(0)模拟出队,但是时间效率低。

一般用collections.deque实现。append()模拟入队,popleft()模拟出队。

from collections import deque
queue = deque(["Eric", "John", "Michael"])
queue.append("Terry")           # Terry arrives
queue.append("Graham")          # Graham arrives
queue.popleft()                 # The first to arrive now leaves

queue.popleft()                 # The second to arrive now leaves

queue                           # Remaining queue in order of arrival

2. 元组

元组是不可变序列,通常用于存储多项集。或用于需要数据不可变的情况(如存储到set中)。

2.1 元组的创建

可以用多种方式构建元组:

  • 使用一对圆括号来表示空元组: ()

  • 使用一个后缀的逗号来表示单元组: a,(a,)

  • 使用以逗号分隔的多个项: a, b, c or (a, b, c)

  • 使用内置的 tuple(): tuple()tuple(iterable)

请注意决定生成元组的其实是逗号而不是圆括号。 圆括号只是可选的,生成空元组或需要避免语法歧义的情况除外。 例如,f(a, b, c) 是在调用函数时附带三个参数,而 f((a, b, c)) 则是在调用函数时附带一个三元组。

2.2 元组的操作

元组是不可变序列,实现了所有通用序列的操作。

2.3 扩展内容:命名元组

通过名称访问相比通过索引访问清晰collections.namedtuple() 提供了命名元组的方法。

collections.namedtuple(typename, field_names, *, rename=False, defaults=None, module=None)

返回一个新的元组子类,名为 typename 。这个新的子类用于创建类元组的对象,可以通过字段名来获取属性值,同样也可以通过索引和迭代获取值。

子类实例同样有文档字符串(类名和字段名)。另外一个有用的 __repr__() 方法,以 name=value 格式列明了元组内容。

field_names 是一个像 [‘x’, ‘y’] 一样的字符串序列。 field_names 也可以是一个纯字符串,用空白或逗号分隔开元素名,比如 'x y' 或者 'x, y'

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y']) #namedtuple('Point', 'x, y')
p = Point(1, 2)
print(p[0] + p[1])
print(p.x + p.y)

命名元组尤其有用于赋值 csv sqlite3 模块返回的元组

EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')

import csv
for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
    print(emp.name, emp.title)

除了继承元组的方法,命名元组还支持三个额外的方法和两个属性。为了防止字段名冲突,方法和属性以下划线开始。

三个方法

classmethod somenamedtuple._make(iterable)

类方法从存在的序列或迭代实例创建一个新实例。

t = [11, 22]
Point._make(t)

somenamedtuple._asdict()

返回一个新的 dict ,它将字段名称映射到它们对应的值:

p = Point(x=11, y=22)
p._asdict()
#{'x': 11, 'y': 22}

somenamedtuple._replace(**kwargs)

返回一个新的命名元组实例,并将指定域替换为新的值

p = Point(x=11, y=22)
p._replace(x=33)

两个属性

somenamedtuple._fields

字符串元组列出了字段名。用于提醒和从现有元组创建一个新的命名元组类型。

p._fields            # view the field names

Color = namedtuple('Color', 'red green blue')
Pixel = namedtuple('Pixel', Point._fields + Color._fields)
Pixel(11, 22, 128, 255, 0)

somenamedtuple._field_defaults

字典将字段名称映射到默认值。

Account = namedtuple('Account', ['type', 'balance'], defaults=[0])
Account._field_defaults
# {'balance': 0}
Account('premium')
# Account(type='premium', balance=0)

要获取这个名字域的值,使用 getattr() 函数 :

getattr(p, 'x')

转换一个字典到命名元组,使用 ** 两星操作符

d = {'x': 11, 'y': 22}
Point(**d)

命名元组是一个正常的Python类,它可以很容易的通过子类更改功能。

class Point(namedtuple('Point', ['x', 'y'])):
    __slots__ = ()
    @property
    def hypot(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5
    def __str__(self):
        return 'Point: x=%6.3f  y=%6.3f  hypot=%6.3f' % (self.x, self.y, self.hypot)

for p in Point(3, 4), Point(14, 5/7):
    print(p)

通过直接赋值给 __doc__ 属性,更改文档字符串

Book = namedtuple('Book', ['id', 'title', 'authors'])
Book.__doc__ += ': Hardcover book in active collection'
Book.id.__doc__ = '13-digit ISBN'
Book.title.__doc__ = 'Title of first printing'
Book.authors.__doc__ = 'List of authors sorted by last name'
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容