Python中列表/元组/集合/字典的理解

论坛 期权论坛 脚本     
匿名技术用户   2021-1-14 15:10   775   0

1 列表/元组/集合/字典的理解

(1)列表是任意对象的序列。列表用方括号表示。

(2)将一组值打包到一个对象中,称为元组。元组用圆括号表示。元组和列表的大部分操作相同。但是,列表是不固定的,可以随时插入,删除;而元组一旦确认就不能够再更改。所以,系统为了列表的灵活性,就需要牺牲掉一些内存;而元组就更为紧凑。(注意,元组在定义过程中,字符串必须用单引号‘扩起来。)

(3)与列表和元组不同,集合是无序的,也不能通过索引进行访问。此外,集合中的元素不能重复。

(4)字典就是一个关联数组或散列表,其中包含通过关键字索引的对象。用大括号表示。与集合相比,通过关键字索引,所以比集合访问方便。字典是Python解释器中最完善的数据类型。


元组举例,

[python] view plain copy
  1. mylist = set([2,2,2,2,2,2,3,3,3,3])
如果要显示mylist,结果会只有 1个2和1个3。


列表里统计重复项个数:

[python] view plain copy
  1. mylist = [2,2,2,2,2,2,3,3,3,3]
  2. mylist.sort()
  3. myset = set(mylist)
  4. for item in myset:
  5. print mylist.count(item), " of ", item, " in list"

2 列表的方法

list. append ( x ):把一个元素添加到链表的结尾,相当于a[len(a):] = [x] list. extend ( L ):将一个给定列表中的所有元素都添加到另一个列表中,相当于a[len(a):] = L list.insert(i,x):在指定位置插入一个元素。第一个参数是准备插入到其前面的那个元素的索引,例如 a.insert(0,x) 会插入到整个链表之前,而 a.insert(len(a),x) 相当于 a.append(x) list.remove(x):删除链表中值为x 的第一个元素。如果没有这样的元素,就会返回一个错误。 list.pop([i])从链表的指定位置删除元素,并将其返回。如果没有指定索引,a.pop() 返回最后一个元素。元素随即从链表中被删除。(方法中i 两边的方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在 Python 库参考手册中遇到这样的标记。) list.index(x): 返回链表中第一个值为 x 的元素的索引。如果没有匹配的元素就会返回一个错误。 list.count(x) :返回x 在链表中出现的次数。 list.sort() :对链表中的元素就地进行排序。 list.reverse() :就地倒排链表中的元素。

3 函数式编程工具

对于链表来讲,有三个内置函数非常有用: filter(),map(), 以及reduce()

分别举例:

>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> seq = range(8)
>>> def add(x, y): return x+y
...
>>> map(add, seq, seq)
[0, 2, 4, 6, 8, 10, 12, 14]

>>> def add(x,y): return x+y
...
>>> reduce(add, range(1, 11))
55

map(function,sequence) 为每一个元素依次调用 function(item) 并将返回值组成一个链表返回。例如,以下程序计算立方:

可以传入多个序列,函数也必须要有对应数量的参数,执行时会依次用各序列上对应的元素来调用函数(如果某些序列比其它的短,就用None 来代替)。如果把 None 做为一个函数传入,则直接返回参数做为替代。例如:

reduce(function, sequence) 返回一个单值,它是这样构造的:首先以序列的前两个元素调用函数 function,再以返回值和第三个参数调用,依次执行下去。例如,以下程序计算 1 到 10 的整数之和:

如果序列中只有一个元素,就返回它,如果序列是空的,就抛出一个异常。

可以传入第三个参数作为初始值。如果序列是空的,就返回初始值,否则函数会先接收初始值和序列的第一个元素,然后是返回值和下一个元素,依此类推。例如:

>>> def sum(seq):
...     def add(x,y): return x+y
...     return reduce(add, seq, 0)
...
>>> sum(range(1, 11))
55
>>> sum([])
0
4 列表推导式

列表推导式为从序列中创建列表提供了一个简单的方法。 普通的应用程序通过将一些操作应用于序列的每个成员并通过返回的元素创建列表,或者通过满足特定条件的元素创建子序列。

例如, 假设我们创建一个 squares 列表, 可以像下面方式:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
我们同样能够达到目的采用下面的方式:

squares = [x**2 for x in range(10)]
这也相当于 squares = map(lambda x: x**2, range(10)) ,但是上面的方式显得简洁以及具有可读性.

列表推导式由包含一个表达式的括号组成,表达式后面跟随一个 for 子句,之后可以有零或多个 forif 子句。 结果是一个列表,由表达式依据其后面的 forif 子句上下文计算而来的结果构成。

例如,如下的列表推导式结合两个列表的元素,如果元素之间不相等的话:

>>> [(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)]

值得注意的是在上面两个方法中的 forif 语句的顺序。

如果想要得到一个元组,必须要加上括号:

>>> 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 "<stdin>", 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]
列表推导式可使用复杂的表达式和嵌套函数:

>>> 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 嵌套的列表推导式

列表推导式可以嵌套。

考虑以下的 3x4 矩阵, 一个列表中包含三个长度为4的列表:

>>> matrix = [
...     [1, 2, 3, 4],
...     [5, 6, 7, 8],
...     [9, 10, 11, 12],
... ]

现在,如果你想交换行和列,可以用嵌套的列表推导式:

>>> [[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]]

在实际中,你应该更喜欢使用内置函数组成复杂流程语句。 对此种情况 zip() 函数将会做的更好:

>>> list(zip(*matrix))
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

更多关于本行中使用的星号的说明,参考 参数列表的分拆

6 循环技巧

在序列中循环时,索引位置和对应值可以使用 enumerate() 函数同时得到:

>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print(i, v)
...
0 tic
1 tac
2 toe
同时循环两个或更多的序列,可以使用 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.
需要逆向循环序列的话,先正向定位序列,然后调用 reversed() 函数:

>>> for i in reversed(xrange(1, 10, 2)):
...     print(i)
...
9
7
5
3
1
要按排序后的顺序循环序列的话,使用 sorted() 函数,它不改动原序列,而是生成一个新的已排序的序列:

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print f
...
apple
banana
orange
pear

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP