python1234出栈_《Python官方文档》5.数据结构

数据结构

本章会更细节的讲一些你已经学过的东西,同时也会加一些新的内容。

5.1 List有关方法

list有许多方法,以下是list方法的所有实例: list.append(x)添加1个item到list的末尾,等同于a[len(a):] = [x] list.extend(iterable)以迭代器方式追加的所有item拓展list,等同于a[len(a):] = iterable list.insert(x)把x插入到list的指定位置。第一个参数是插入的位置,a.insert(0, x)插入到list头, a.insert(len(a), x)相当于a.append(x)。 list.remove(x)移除list中第一个等于x的item。如果没有这个item会报错 list.pop([i])移除list中指定位置的item,同时返回item。如果位置没有指定,a.pop()'会移除list的最后1个item,并返回它。中括号中的参数x是可选的,中括号不是必须的。你在Python手册中会经常看见这种用法。list.clear() 清空list,等同于del a[:]list.index(x[, start[, end]]) 返回第一个等于x的item的序列位置,是从0开始算。如果没有等于x的item方法会报ValueError。 可选参数作为切片使用,定义了起始和结束位置。返回的位置是相对于原先完整的list而不是起始参数。list.count(x) 返回list中x出现的次数list.sort(key=None, reverse=False) 本地对list排序(参数是拿来定义sort,去sorted()看具体的解释吧)list.reverse() 不需要额外空间,倒排list。list.copy() 返回list的浅拷贝。相当于a[:]`

以下实例使用了上述大部分方法: fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana'] fruits.count('apple') 2 fruits.count('tangerine') 0 fruits.index('banana') 3 fruits.index('banana', 4) # Find next banana starting a position 4 6 fruits.reverse() fruits ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange'] fruits.append('grape') fruits ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape'] fruits.sort() fruits ['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear'] fruits.pop() 'pear'你也许注意到,像insert, remove, sort方法仅修改list本身 仅返回None。这是Python 可变数据结构的设计哲学。

5.1.1 像栈一样使用list

list这些方法使得list非常容易像栈一样被使用,最后1个插入的元素首先被取出,添加到栈顶使用append();获取栈顶元素使用pop(),不需要特别指定次序:

fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']

fruits.count('apple')

2

fruits.count('tangerine')

0

fruits.index('banana')

3

fruits.index('banana', 4) # Find next banana starting a position 4

6

fruits.reverse()

fruits

['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']

fruits.append('grape')

fruits

['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']

fruits.sort()

fruits

['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']

fruits.pop()

'pear'

5.1.2 像队列一样使用list

当然也可以把list作为队列,先进先出,但是,作为队列list并不高效。因为从list尾部追加删除原色很快,但是从list头做同样操作就很慢了,因为其他所有元素都要移动1次。 真要实现队列,请使用collections.deque这个专门的数据结构,它2端插入提取都很快:

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

'Eric'

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

'John'

queue # Remaining queue in order of arrival

deque(['Michael', 'Terry', 'Graham'])

5.1.3 List 列表解析式

list 的列表解析式提供了一种简洁的创建list的方法。在以下场景我们常使用list列表解析式:生成1个新的list,它的元素是有原始序列数据结构中取出每个元素操作;或者产生原始序列结构的子集。 比如说你想创建原始list的平方list:

squares = []

for x in range(10):

... squares.append(x**2)

...

squares

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

注意到以上代码会创建一个变量x,它在循环后仍就存在。为了消除这个副作用:

squares = list(map(lambda x: x**2, range(10)))

等同与:

squares = [x**2 for x in range(10)]

这更简洁易懂。 列表解析式在for前后再添加个for或者if。新生成的list会由最外围中括号的for if来计算。举个例子,以下代码混合了2个list中互相不等的元素到新的list。

[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]

[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

等于

combs = []

for x in [1,2,3]:

... for y in [3,1,4]:

... if x != y:

... combs.append((x, y))

...

combs

[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

如果[]中的表达式是tuple,像前面例子 (x,y),它必须是在括号内。

vec = [-4, -2, 0, 2, 4]

# create a new list with the values doubled

[x*2 for x in vec]

[-8, -4, 0, 4, 8]

# filter the list to exclude negative numbers

[x for x in vec if x >= 0]

[0, 2, 4]

# apply a function to all the elements

[abs(x) for x in vec]

[4, 2, 0, 2, 4]

# call a method on each element

freshfruit = [' banana', ' loganberry ', 'passion fruit ']

[weapon.strip() for weapon in freshfruit]

['banana', 'loganberry', 'passion fruit']

# create a list of 2-tuples like (number, square)

[(x, x**2) for x in range(6)]

[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]

# the tuple must be parenthesized, otherwise an error is raised

[x, x**2 for x in range(6)]

File "", line 1, in

[x, x**2 for x in range(6)]

^

SyntaxError: invalid syntax

# flatten a list using a listcomp with two 'for'

vec = [[1,2,3], [4,5,6], [7,8,9]]

[num for elem in vec for num in elem]

[1, 2, 3, 4, 5, 6, 7, 8, 9]

list列表表达式中科院包含更复杂的表达和运算:

from math import pi

[str(round(pi, i)) for i in range(1, 6)]

['3.1', '3.14', '3.142', '3.1416', '3.14159']

5.1.4 列表解析式的细节

最初的列表解析式中科院包含任何二元运算符,包括另一个列表解析式。下面这个list是一个3*4的矩阵:

matrix = [

... [1, 2, 3, 4],

... [5, 6, 7, 8],

... [9, 10, 11, 12],

... ]

以下代码将上面的3*4矩阵进行转置:

[[row[i] for row in matrix] for i in range(4)]

[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

就像我们在上一节看到的,内置的列表解析式其实就是for中的上下文操作,上面的例子等于:

transposed = []

for i in range(4):

... transposed.append([row[i] for row in matrix])

...

transposed

[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

同样的,也等于:

transposed = []

for i in range(4):

... # the following 3 lines implement the nested listcomp

... transposed_row = []

... for row in matrix:

... transposed_row.append(row[i])

... transposed.append(transposed_row)

...

transposed

[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

在真实代码场景中,你更应该使用Python的内置方法进行以上复杂的操作。zip()起相同的作用:

list(zip(*matrix))

[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

看 Unpacking Argument Lists 这一节能得到上面代码的更多细节。

5.2 删除语句

根据次序移除list中的元素。与pop()不同,pop()返回弹出的元素,它不返回。del还可以切片的删除list元素,或者清空整个list,早先我们有个这样的例子。

a = [-1, 1, 66.25, 333, 333, 1234.5]

del a[0]

a

[1, 66.25, 333, 333, 1234.5]

del a[2:4]

a

[1, 66.25, 1234.5]

del a[:]

a

[]

del 可以删除完整的变量 del a删除变量a之后我们再引用该变量会报错,我们之后还会探索del的其他用法。

5.3 Tuple 和 Sequence

我们注意到list和字符串有许多共同点,比如说索引和切片操作。以下是2个序列数据类型的例子(具体请看Sequence Types --- list, tuple, range)。由于Python一直在进化,也许会有更多的序列数据类型加入。下面是另外一种标准库里的序列数据类型:tuple.一个tuple包含了一系列被逗号隔开的数据,比如说:

t = 12345, 54321, 'hello!'

t[0]

12345

t

(12345, 54321, 'hello!')

# Tuples may be nested:

... u = t, (1, 2, 3, 4, 5)

u

((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

# Tuples are immutable:

... t[0] = 88888

Traceback (most recent call last):

File "", line 1, in

TypeError: 'tuple' object does not support item assignment

# but they can contain mutable objects:

... v = ([1, 2, 3], [3, 2, 1])

v

([1, 2, 3], [3, 2, 1])

输出tuple总是被括号包围,它里面的tuple有木有括号都能被解释正确;即使括号是必须的,它们的输入tuple也不一定有括号包围。不可以对tuple中的单个元素复制,但是,tuple中的元素是可变对象时,可以被改变,比如说list。 即使tuple和list看着蛮像,但它们通常在不同的情景不同的目的下使用。Tuple是不可变的,通常是包含了各种各样的序列元素,这些元素可以通过解包(后面会提到)或者指定位置来触达。List是可变的,元素通常是同一类的,我们可以通过迭代器遍历整个list。 必须提到的是,构造tuple的时候。空tuple由一对括号初始化,1个元素的tuple初始化应当由1个值和逗号组成。看着丑但是有效哦。

empty = ()

singleton = 'hello', #

len(empty)

0

len(singleton)

1

singleton

('hello',)

t = 12345, 54321, 'hello!'是tuple解包的例子,12345,54321,'hello'都是tuple的元素。反过来的操作如下: x, y, z = t以上序列解包操作适用于任何等式右边的序列。序列解包操作要求等式左边的变量个数等同于右边序列的原色个数。当然多元赋值也是可以的,只是右边序列解包操作出来的元素混进tuple输出。

5.4 集合(Sets)

Python引入Set这种无序的,无重复元素的数据结构。我们通常用它来消除重复元素和进行隶属测试。Set也支持一些数学操作 ,交,并,差,对称差。 用中括号或set()来新建sets,需要注意的是,新建空set必须使用set()而不是{},后者是新建dict,我们下一章再讨论dict。 下面是set的简要使用:

basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}

print(basket) # show that duplicates have been removed

{'orange', 'banana', 'pear', 'apple'}

'orange' in basket # fast membership testing

True

'crabgrass' in basket

False

# Demonstrate set operations on unique letters from two words

...

a = set('abracadabra')

b = set('alacazam')

a # unique letters in a

{'a', 'r', 'b', 'c', 'd'}

a - b # letters in a but not in b

{'r', 'd', 'b'}

a | b # letters in a or b or both

{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}

a & b # letters in both a and b

{'a', 'c'}

a ^ b # letters in a or b but not both

{'r', 'd', 'b', 'm', 'z', 'l'}

与list列表解析式类似,set也支持这样操作:

a = {x for x in 'abracadabra' if x not in 'abc'}

a

{'r', 'd'}

5.5 字典(Dictionaries)

另一个很有用的Python内置数据结构是字典。Dictionaries有时在其他计算机语言里,作为对应储存,对应序列。不比被顺序索引的序列数据类型,Dictionaries是不可变的结构,它被key索引,字符串,数字经常被用作key。Tuple也可以被用作key,只要它仅由数字,字符串或者tuple组成,如果该Tuple直接或间接包含可变对象,那它就不能被用作dictionary的key了。也不能把list用作dictionary的key,因为list不需要额外空间就能被指定索引修改,切片或appen(),enxtend()这样的方法。 对dictionary最好的理解是一个无序的键值对,key在这个dictionary是独一无二的。一对中括号可以创建一个空dictionary。用逗号分隔,按照key:value这样的格式,由{}包围,可以初始化一个dictionary,这也是dictionary输出的格式。 dictionary的主要用法是储存键值对以及通过key拿到value。通过del也能删除一个键值对。如果1个key已经使用,再使用它的值会被更新。用一个不存在的键来取值会报错。 list(d.keys())可以以list的形式随机随机顺序获取dictionary的键,当然可以使用sorted(d.keys()获取顺序键list。想知道一个键是否存在于dictionary,使用in。 这里有些dictionary使用的小例子:

python

tel = {'jack': 4098, 'sape': 4139}

tel['guido'] = 4127

tel

{'sape': 4139, 'guido': 4127, 'jack': 4098}

tel['jack']

4098

del tel['sape']

tel['irv'] = 4127

tel

{'guido': 4127, 'irv': 4127, 'jack': 4098}

list(tel.keys())

['irv', 'guido', 'jack']

sorted(tel.keys())

['guido', 'irv', 'jack']

'guido' in tel

True

'jack' not in tel

False

dict()可以从键值对序列构建一个dictionary:

dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])

{'sape': 4139, 'jack': 4098, 'guido': 4127}

dictionary解析式可以用键值对来创建dictionary。

{x: x**2 for x in (2, 4, 6)}

{2: 4, 4: 16, 6: 36}

当键是简单字符串时,经常用关键词等式来创建1个dict。

dict(sape=4139, guido=4127, jack=4098)

{'sape': 4139, 'jack': 4098, 'guido': 4127}

5.6 遍历方法

通过items()可以同时遍历dictionary的键值对。

knights = {'gallahad': 'the pure', 'robin': 'the brave'}

for k, v in knights.items():

... print(k, v)

gallahad the pure

robin the brave

enumerate()可以遍历序列同时得到索引和对应元素

for i, v in enumerate(['tic', 'tac', 'toe']):

... print(i, v)

...

0 tic

1 tac

2 toe

要同时遍历2个或者更多的序列数据结构,可以通过zip()。

questions = ['name', 'quest', 'favorite color']

answers = ['lancelot', 'the holy grail', 'blue']

for q, a in zip(questions, answers):

... print('What is your {0}? It is {1}.'.format(q, a))

...

What is your name? It is lancelot.

What is your quest? It is the holy grail.

What is your favorite color? It is blue.

要反向遍历序列,首先要指定list头,然后把改list作为reversed()的参数执行。

for i in reversed(range(1, 10, 2)):

... print(i)

...

9

7

5

3

1

要遍历一个序列,使用sorted对原始list操作会输出一个新的有序list,但是原始list不变。

basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']

for f in sorted(set(basket)):

... print(f)

...

apple

banana

orange

pear

在遍历list的时候有时候想修改它,与其修改不如建立个新的list,这样更简单更方便。

import math

raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]

filtered_data = []

for value in raw_data:

... if not math.isnan(value):

... filtered_data.append(value)

...

filtered_data

[56.2, 51.7, 55.3, 52.5, 47.8]

5.7 条件语句

if和while语句中包含的条件语句,可不仅仅只是比较,可以是任何操作符。 in 和not操作是原来确认值是否存在于序列中。is和is not是确认2个实例对象是否相同;它仅可以作用于可变对象例如说list这样。所有的比较操作符都有相同的运算优先级,都低于数字操作符。 比较操作可以连起来。比如说a

string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'

non_null = string1 or string2 or string3

non_null

Trondheim

不像C语言,Python的复制操作不能在操作符运算中出现。C语言开发者也许会对此困惑,但这条禁令有效的避免了C语言中常常出现的一种错误:在表达式中输入=而在此场景中需要的是==。

5.8. 序列结构和其他数据结构类型的比较操作

序列结构实例也许会和另外的相同数据结构的实例进行比较操作。比较操作会按照字母顺序:2个序列的第一个元素比较,如果它们不同,那输出比较操作;如果相同,下一对元素进行比较,直到一方元素遍历结束。如果是相同类型的序列结构,字母级比较操作还会递归进行。如果所有的元素都相同,那我们任务这俩序列结构的实例是相同的。如果一个是另外一个的子集,那短的就是小的那一个。字母级比较使用字符串的Unicode编码顺序来比较。下面是例子

(1, 2, 3) < (1, 2, 4)

[1, 2, 3] < [1, 2, 4]

'ABC' < 'C' < 'Pascal' < 'Python'

(1, 2, 3, 4) < (1, 2, 4)

(1, 2) < (1, 2, -1)

(1, 2, 3) == (1.0, 2.0, 3.0)

(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)

比较2个不同数据类型的实例也是可以的,只要比较的对象都有合适的方法。比如说不同的数字类型比较时,比较对象会转换成它们的数值,如0变成0.0。除此之外,解释器都会报TypeError异常。

原创文章,转载请注明: 转载自并发编程网 -- ifeve.com本文链接地址: 《Python官方文档》5.数据结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值