Python 编程/列表
Python 中的列表是有序的一组项目(或元素)。它是一个非常通用的结构,列表元素不必是相同类型:你可以在同一个列表中放置数字、字母、字符串和嵌套列表。
Python 中的列表概览
list1 = [] # A new empty list
list2 = [1, 2, 3, "cat"] # A new non-empty list with mixed item types
list1.append("cat") # Add a single member, at the end of the list
list1.extend(["dog", "mouse"]) # Add several members
list1.insert(0, "fly") # Insert at the beginning
list1[0:0] = ["cow", "doe"] # Add members at the beginning
doe = list1.pop(1) # Remove item at index
if "cat" in list1: # Membership test
list1.remove("cat") # Remove AKA delete
#list1.remove("elephant") - throws an error
for item in list1: # Iteration AKA for each item
print(item)
print("Item count:", len(list1))# Length AKA size AKA item count
list3 = [6, 7, 8, 9]
for i in range(0, len(list3)): # Read-write iteration AKA for each item
list3[i] += 1 # Item access AKA element access by index
last = list3[-1] # Last item
nextToLast = list3[-2] # Next-to-last item
isempty = len(list3) == 0 # Test for emptiness
set1 = set(["cat", "dog"]) # Initialize set from a list
list4 = list(set1) # Get a list from a set
list5 = list4[:] # A shallow list copy
list4equal5 = list4==list5 # True: same by value
list4refEqual5 = list4 is list5 # False: not same by reference
list6 = list4[:]
del list6[:] # Clear AKA empty AKA erase
list7 = [1, 2] + [2, 3, 4] # Concatenation
print(list1, list2, list3, list4, list5, list6, list7)
print(list4equal5, list4refEqual5)
print(list3[1:3], list3[1:], list3[:2]) # Slices
print(max(list3 ), min(list3 ), sum(list3)) # Aggregates
print([x for x in range(10)]) # List comprehension
print([x for x in range(10) if x % 2 == 1])
print([x for x in range(10) if x % 2 == 1 if x < 5])
print([x + 1 for x in range(10) if x % 2 == 1])
print([x + y for x in '123' for y in 'abc'])
在 Python 中创建列表有两种不同的方法。第一种是通过赋值(“静态”),第二种是使用列表推导式(“动态”)。
要创建一个静态的项目列表,请将它们写在方括号之间。例如
[ 1,2,3,"This is a list",'c',Donkey("kong") ]
观察
- 列表包含不同数据类型的项目:整数、字符串和 Donkey 类。
- 对象可以在“运行时”创建并添加到列表中。最后一项是 Donkey 类的新实例。
创建一个新列表,其成员由非文字表达式构建
a = 2
b = 3
myList = [a+b, b+a, len(["a","b"])]
使用列表推导式,你可以描述创建列表的过程。为此,列表被分成两部分。第一部分是每个元素的样子,第二部分是你如何得到它的过程。
例如,假设我们有一个单词列表
listOfWords = ["this","is","a","list","of","words"]
要获取每个单词的首字母并使用列表推导式创建列表,我们可以这样做
>>> listOfWords = ["this","is","a","list","of","words"]
>>> items = [ word[0] for word in listOfWords ]
>>> print(items)
['t', 'i', 'a', 'l', 'o', 'w']
列表推导式支持多个 for 语句。它将按顺序评估所有对象中的项目,如果一个对象比其他对象更长,则会循环遍历较短的对象。
>>> item = [x+y for x in 'cat' for y in 'pot']
>>> print(item)
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']
列表推导式支持 if 语句,以便仅将满足特定条件的成员包含到列表中
>>> print([x+y for x in 'cat' for y in 'pot'])
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']
>>> print([x+y for x in 'cat' for y in 'pot' if x != 't' and y != 'o' ])
['cp', 'ct', 'ap', 'at']
>>> print([x+y for x in 'cat' for y in 'pot' if x != 't' or y != 'o' ])
['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'tt']
在 2.x 版本中,Python 的列表推导式不会定义作用域。在评估完成后,任何在评估中绑定的变量都保持绑定到它们最后绑定的值。在 3.x 版本中,Python 的列表推导式使用局部变量
>>> print(x, y) #Input to python version 2
t t #Output using python 2
>>> print(x, y) #Input to python version 3
NameError: name 'x' is not defined #Python 3 returns an error because x and y were not leaked
这与将推导式扩展为显式嵌套的一组或多组“for”语句和 0 或多个“if”语句完全相同。
你可以将一个列表初始化为一个大小,每个元素都有一个初始值
>>> zeros=[0]*5
>>> print zeros
[0, 0, 0, 0, 0]
这对任何数据类型都有效
>>> foos=['foo']*3
>>> print(foos)
['foo', 'foo', 'foo']
但有一个需要注意的地方。当通过乘法构建一个新列表时,Python 通过引用复制每个项目。这对可变项目来说是一个问题,例如在多维数组中,每个元素本身都是一个列表。你会认为生成二维数组的简单方法是
listoflists=[ [0]*4 ] *5
这有效,但可能不会按照你的预期执行
>>> listoflists=[ [0]*4 ] *5
>>> print(listoflists)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> listoflists[0][2]=1
>>> print(listoflists)
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0]]
这里发生的事情是 Python 使用相同的内部列表引用作为外部列表的元素。查看这个问题的另一个方法是检查 Python 如何看待上述定义
>>> innerlist=[0]*4
>>> listoflists=[innerlist]*5
>>> print(listoflists)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> innerlist[2]=1
>>> print(listoflists)
[[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0]]
假设上述效果不是你想要的,解决这个问题的一种方法是使用列表推导式
>>> listoflists=[[0]*4 for i in range(5)]
>>> print(listoflists)
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> listoflists[0][2]=1
>>> print(listoflists)
[[0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
要查找列表的长度,请使用内置的 len() 方法。
>>> len([1,2,3])
3
>>> a = [1,2,3,4]
>>> len( a )
4
列表可以通过几种方式组合。最简单的方法就是将它们“加”在一起。例如
>>> [1,2] + [3,4]
[1, 2, 3, 4]
另一种组合列表的方法是使用extend。如果你需要在 lambda 中组合列表,extend 是最好的方法。
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a.extend(b)
>>> print(a)
[1, 2, 3, 4, 5, 6]
另一种将值追加到列表的方法是使用append。例如
>>> p=[1,2]
>>> p.append([3,4])
>>> p
[1, 2, [3, 4]]
>>> # or
>>> print(p)
[1, 2, [3, 4]]
但是,[3,4] 是列表的一个元素,而不是列表的一部分。append 总是将一个元素添加到列表的末尾。因此,如果目的是连接两个列表,请始终使用extend。
与字符串类似,列表可以被索引和切片
>>> list = [2, 4, "usurp", 9.0, "n"]
>>> list[2]
'usurp'
>>> list[3:]
[9.0, 'n']
就像字符串的切片是一个子字符串一样,列表的切片也是一个列表。但是,列表与字符串不同的是,我们可以为列表中的项目分配新值
>>> list[1] = 17
>>> list
[2, 17, 'usurp', 9.0, 'n']
我们可以为列表的切片分配新值,它们甚至不必是相同长度
>>> list[1:4] = ["opportunistic", "elk"]
>>> list
[2, 'opportunistic', 'elk', 'n']
甚至可以通过将新值分配给空切片来将项目追加到列表的开头
>>> list[:0] = [3.14, 2.71]
>>> list
[3.14, 2.71, 2, 'opportunistic', 'elk', 'n']
类似地,你可以通过在末尾指定空切片来将项目追加到列表的末尾
>>> list[len(list):] = ['four', 'score']
>>> list
[3.14, 2.71, 2, 'opportunistic', 'elk', 'n', 'four', 'score']
你也可以完全更改列表的内容
>>> list[:] = ['new', 'list', 'contents']
>>> list
['new', 'list', 'contents']
列表赋值语句的右侧可以是任何可迭代类型
>>> list[:2] = ('element',('t',),[])
>>> list
['element', ('t',), [], 'contents']
使用切片可以创建列表的副本,因为切片返回一个新的列表
>>> original = [1, 'element', []]
>>> list_copy = original[:]
>>> list_copy
[1, 'element', []]
>>> list_copy.append('new element')
>>> list_copy
[1, 'element', [], 'new element']
>>> original
[1, 'element', []]
但是,请注意,这是一个浅拷贝,它包含对原始列表中元素的引用,因此请谨慎使用可变类型
>>> list_copy[2].append('something')
>>> original
[1, 'element', ['something']]
也可以获取数组的非连续部分。如果想获取列表中每个第 n 个元素,可以使用 :: 运算符。语法是 a:b:n,其中 a 和 b 是要操作的切片的开始和结束位置。
>>> list = [i for i in range(10) ]
>>> list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list[::2]
[0, 2, 4, 6, 8]
>>> list[1:7:2]
[1, 3, 5]
列表可以比较是否相等。
>>> [1,2] == [1,2]
True
>>> [1,2] == [3,4]
False
列表可以使用小于运算符进行比较,该运算符使用字典序
>>> [1,2] < [2,1]
True
>>> [2,2] < [2,1]
False
>>> ["a","b"] < ["b","a"]
True
排序概览
list1 = [2, 3, 1, 'a', 'B']
list1.sort() # list1 gets modified, case sensitive
list2 = sorted(list1) # list1 is unmodified; since Python 2.4
list3 = sorted(list1, key=lambda x: x.lower()) # case insensitive ; will give error as not all elements of list are strings and .lower() is not applicable
list4 = sorted(list1, reverse=True) # Reverse sorting order: descending
print(list1, list2, list3, list4)
使用 sort 方法可以轻松地对列表进行排序。
>>> list1 = [2, 3, 1, 'a', 'b']
>>> list1.sort()
>>> list1
[1, 2, 3, 'a', 'b']
请注意,列表是在原地排序的,sort() 方法返回None 来强调这种副作用。
如果你使用的是 Python 2.4 或更高版本,则有一些额外的排序参数
- sort(cmp,key,reverse)
- cmp : 用于确定任何两个元素之间相对顺序的函数
- key : 用于获取要对任何元素进行排序的值的函数。
- reverse : sort(reverse=True) 或 sort(reverse=False)
Python 还包含一个 sorted() 函数。
>>> list1 = [5, 2, 3, 'q', 'p']
>>> sorted(list1)
[2, 3, 5, 'p', 'q']
>>> list1
[5, 2, 3, 'q', 'p']
请注意,与 sort() 方法不同,sorted(list) 不会在原地对列表进行排序,而是返回排序后的列表。sorted() 函数与 sort() 方法一样也接受 reverse 参数。
链接
- 2. 内置函数 # sorted,docs.python.org
- 排序 HOW TO,docs.python.org
列表迭代
只读迭代列表,也称为列表的每个元素
list1 = [1, 2, 3, 4]
for item in list1:
print(item)
可写迭代列表
list1 = [1, 2, 3, 4]
for i in range(0, len(list1)):
list1[i]+=1 # Modify the item at an index as you see fit
print(list)
从一个数字到另一个数字,步长为一个数字
for i in range(1, 13+1, 3): # For i=1 to 13 step 3
print(i)
for i in range(10, 5-1, -1): # For i=10 to 5 step -1
print(i)
满足条件的列表中每个元素(过滤)
for item in list:
if not condition(item):
continue
print(item)
删除也称为删除索引处的项目(另见#pop(i))
list1 = [1, 2, 3, 4]
list1.pop() # Remove the last item
list1.pop(0) # Remove the first item , which is the item at index 0
print(list1)
list1 = [1, 2, 3, 4]
del list1[1] # Remove the 2nd element; an alternative to list.pop(1)
print(list1)
按值删除元素
list1 = ["a", "a", "b"]
list1.remove("a") # Removes only the 1st occurrence of "a"
print(list1)
通过复制旧列表中的过滤选择项来创建一个新列表
list1 = [1, 2, 3, 4]
newlist = [item for item in list1 if item > 2]
print(newlist)
这使用了列表推导.
通过使用"[:]"来更新列表,保留其中过滤后的项目选择
list1 = [1, 2, 3, 4]
sameList = list1
list1[:] = [item for item in list1 if item > 2]
print(sameList, sameList is list1)
对于更复杂的条件,可以使用单独的函数来定义标准
list1 = [1, 2, 3, 4]
def keepingCondition(item):
return item > 2
sameList = list1
list1[:] = [item for item in list1 if keepingCondition(item)]
print(sameList, sameList is list1)
在迭代列表时删除项目通常会导致意外结果,除非您使用索引小心地进行操作
list1 = [1, 2, 3, 4]
index = len(list1)
while index > 0:
index -= 1
if not list1[index] < 2:
list1.pop(index)
链接
- 在迭代时从列表中删除项目,stackoverflow.com
有一些针对列表的算术聚合的内置函数。这些包括最小值、最大值和总和
list = [1, 2, 3, 4]
print(max(list), min(list), sum(list))
average = sum(list) / float(len(list)) # Provided the list is non-empty
# The float above ensures the division is a float one rather than integer one.
print(average)
max 和 min 函数也适用于字符串列表,返回关于字母顺序的最大值和最小值
list = ["aa", "ab"]
print(max(list), min(list)) # Prints "ab aa"
复制也称为克隆列表
制作浅拷贝
list1= [1, 'element']
list2 = list1[:] # Copy using "[:]"
list2[0] = 2 # Only affects list2, not list1
print(list1[0]) # Displays 1
# By contrast
list1 = [1, 'element']
list2 = list1
list2[0] = 2 # Modifies the original list
print(list1[0]) # Displays 2
上述操作不会进行深拷贝,这有以下后果
list1 = [1, [2, 3]] # Notice the second item being a nested list
list2 = list1[:] # A shallow copy
list2[1][0] = 4 # Modifies the 2nd item of list1 as well
print(list1[1][0]) # Displays 4 rather than 2
制作深拷贝
import copy
list1 = [1, [2, 3]] # Notice the second item being a nested list
list2 = copy.deepcopy(list1) # A deep copy
list2[1][0] = 4 # Leaves the 2nd item of list1 unmodified
print list1[1][0] # Displays 2
另见#连续切片.
链接
- 8.17. copy — 浅拷贝和深拷贝操作 在 docs.python.org 上
清除列表
del list1[:] # Clear a list
list1 = [] # Not really clear but rather assign to a new empty list
当列表作为参数传递时,使用适当的方法清除列表会产生不同的结果
def workingClear(ilist):
del ilist[:]
def brokenClear(ilist):
ilist = [] # Lets ilist point to a new list, losing the reference to the argument list
list1=[1, 2]; workingClear(list1); print(list1)
list1=[1, 2]; brokenClear(list1); print(list1)
关键字:清空列表、擦除列表、清除列表、清空列表、擦除列表。
从列表中删除重复项(仅保留唯一项)可以通过以下方式实现。
如果列表中的每个项目都是可散列的,使用列表推导,速度很快
list1 = [1, 4, 4, 5, 3, 2, 3, 2, 1]
seen = {}
list1[:] = [seen.setdefault(e, e) for e in list1 if e not in seen]
如果列表中的每个项目都是可散列的,使用索引迭代,速度慢很多
list1 = [1, 4, 4, 5, 3, 2, 3, 2, 1]
seen = set()
for i in range(len(list1) - 1, -1, -1):
if list1[i] in seen:
list1.pop(i)
seen.add(list1[i])
如果某些项目不可散列,则可以将已访问项目集存储在列表中
list1 = [1, 4, 4, ["a", "b"], 5, ["a", "b"], 3, 2, 3, 2, 1]
seen = []
for i in range(len(list1) - 1, -1, -1):
if list1[i] in seen:
list1.pop(i)
seen.append(list1[i])
如果列表中的每个项目都是可散列的,并且不关心元素的顺序
list1 = [1, 4, 4, 5, 3, 2, 3, 2, 1]
list1[:] = list(set(list1)) # Modify list1
list2 = list(set(list1))
在上面使用索引迭代的示例中,扫描是从末尾到开头进行的。当这些示例被改写为从开头到结尾扫描时,结果似乎慢了很多。
链接
- 如何从列表中删除重复项? 在 python.org 编程常见问题解答中
- 从序列中删除重复项(Python 食谱) 在 activestate.com 上
- 从列表中删除重复项 在 stackoverflow.com 上
将项目x添加到列表末尾。
>>> list = [1, 2, 3]
>>> list.append(4)
>>> list
[1, 2, 3, 4]
删除列表中索引i处的项目并将其返回。如果未提供i,则删除列表中的最后一个项目并将其返回。
>>> list = [1, 2, 3, 4]
>>> a = list.pop(0)
>>> list
[2, 3, 4]
>>> a
1
>>> b = list.pop()
>>>list
[2, 3]
>>> b
4
连接两个列表。
通过将给定列表连接给定次数来创建一个新列表。即 list1 * 0 == [];list1 * 3 == list1 + list1 + list1;
运算符'in' 用于两种目的;要么在 for 循环中迭代列表中的每个项目,要么检查列表中是否存在一个值,返回真或假。
>>> list = [1, 2, 3, 4]
>>> if 3 in list:
>>> ....
>>> l = [0, 1, 2, 3, 4]
>>> 3 in l
True
>>> 18 in l
False
>>>for x in l:
>>> print(x)
0
1
2
3
4
要获取两个列表之间的差异,只需迭代
a = [0, 1, 2, 3, 4, 4]
b = [1, 2, 3, 4, 4, 5]
print([item for item in a if item not in b])
# [0]
要获取两个列表之间的交集(通过保留其元素顺序及其倍数),请应用与差异的差异
a = [0, 1, 2, 3, 4, 4]
b = [1, 2, 3, 4, 4, 5]
dif = [item for item in a if item not in b]
print([item for item in a if item not in dif])
# [1, 2, 3, 4, 4]
# Note that using the above on:
a = [1, 1]; b = [1]
# will result in [1, 1]
# Similarly
a = [1]; b = [1, 1]
# will result in [1]
- 使用列表推导构造列表 ['ab', 'ac', 'ad', 'bb', 'bc', 'bd']。
- 对上述列表使用切片构造列表 ['ab', 'ad', 'bc']。
- 使用列表推导构造列表 ['1a', '2a', '3a', '4a']。
- 同时从上述列表中删除元素 '2a' 并将其打印出来。
- 复制上述列表并将 '2a' 添加回列表中,这样原始列表中仍然缺少它。
- 使用列表推导构造列表 ['abe', 'abf', 'ace', 'acf', 'ade', 'adf', 'bbe', 'bbf', 'bce', 'bcf', 'bde', 'bdf']
问题 1
List1 = [a + b for a in 'ab' for b in 'bcd'] print(List1) >>> ['ab', 'ac', 'ad', 'bb', 'bc', 'bd']
问题 2
List2 = List1[::2] print(List2) >>> ['ab', 'ad', 'bc']
问题 3
List3 = [a + b for a in '1234' for b in 'a'] print(List3) >>> ['1a', '2a', '3a', '4a']
问题 4
print(List3.pop(List3.index('3a'))) print(List3) >>> 3a >>> ['1a', '2a', '4a']
问题 5
List4 = List3[:] List4.insert(2, '3a') print(List4) >>> ['1a', '2a', '3a', '4a']
问题 6
List5 = [a + b + c for a in 'ab' for b in 'bcd' for c in 'ef'] print(List5) >>> ['abe', 'abf', 'ace', 'acf', 'ade', 'adf', 'bbe', 'bbf', 'bce', 'bcf', 'bde', 'bdf']
- Python 文档,第“序列类型”章 -- python.org
- Python 教程,“列表”章节 -- python.org