列表
列表方法:
方法是与对象(列表、数、字符串等)联系紧密的函数。通常,像下面这样调用方法:
object.method(arguments)
1. append
2. clear
3. copy
方法copy 复制列表。前面说过,常规复制只是将另一个名称关联到列表。
>>> a = [1, 2, 3]
>>> b = a
>>> b[1] = 4
>>> a
[1, 4, 3]
要让a和b指向不同的列表,就必须将b关联到a的副本。
>>> a = [1, 2, 3]
>>> b = a.copy()
>>> b[1] = 4
>>> a
[1, 2, 3]
这类似于使用a[:]或list(a),它们也都复制a。
4. count
5. extend
方法extend让你能够同时将多个值附加到列表末尾,为此可将这些值组成的序列作为参数提
供给方法extend。换而言之,你可使用一个列表来扩展另一个列表。
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> a.extend(b)
>>> a
[1, 2, 3, 4, 5, 6]
这可能看起来类似于拼接,但存在一个重要差别,那就是将修改被扩展的序列(这里是a)。
在常规拼接中,情况是返回一个全新的序列。
>>> a = [1, 2, 3]
>>> b = [4, 5, 6]
>>> a + b
[1, 2, 3, 4, 5, 6]
>>> a
[1, 2, 3]
6. index
方法index在列表中查找指定值第一次出现的索引。
>>> knights = ['We', 'are', 'the', 'knights', 'who', 'say', 'ni']
>>> knights.index('who')
4
7. insert
方法insert用于将一个对象插入列表。
numbers = [1, 2, 3, 5, 6, 7]
numbers.insert(3, 'four')
numbers
[1, 2, 3, 'four', 5, 6, 7]
8. pop
方法pop从列表中删除一个元素(末尾为最后一个元素),并返回这一元素。
>>> x = [1, 2, 3]
>>> x.pop()
3
>>> x
[1, 2]
>>> x.pop(0)
1
>>> x
[2]
注意 pop是唯一既修改列表又返回一个非None值的列表方法。
使用pop可实现一种常见的数据结构——栈(stack)。栈就像一叠盘子,你可在上面添加盘子,
还可从上面取走盘子。最后加入的盘子最先取走,这被为后进先出(LIFO)。
9.remove
方法remove用于删除第一个为指定值的元素。remove
>>> x = ['to', 'be', 'or', 'not', 'to', 'be']
>>> x.remove('be')
>>> x
['to', 'or', 'not', 'to', 'be']
10. reverse
方法reverse按相反的顺序排列列表中的元素(我想你对此应该不会感到惊讶)。
>>> x = [1, 2, 3]
>>> x.reverse()
>>> x
[3, 2, 1]
注意到reverse修改列表,但不返回任何值(与remove和sort等方法一样)。
如果要按相反的顺序迭代序列,可使用函数reversed。这个函数不返回列表,而是返回
一个迭代器(迭代器将在第9章详细介绍)。你可使用list将返回的对象转换为列表。
>>> x = [1, 2, 3]
>>> list(reversed(x))
[3, 2, 1]
11. sort
方法sort用于对列表就地排序①。就地排序意味着对原来的列表进行修改,使其元素按顺序
排列,而不是返回排序后的列表的副本。
>>> x = [4, 6, 2, 1, 7, 9]
>>> x.sort()
>>> x
[1, 2, 4, 6, 7, 9]
前面介绍了多个修改列表而不返回任何值的方法,在大多数情况下,这种行为都相当自然(例
如,对append来说就如此)。需要强调sort的行为也是这样的,因为这种行为给很多人都带来了
困惑。在需要排序后的列表副本并保留原始列表不变时,通常会遭遇这种困惑。为实现这种目标,
一种直观(但错误)的方式是像下面这样做:
>>> x = [4, 6, 2, 1, 7, 9]
>>> y = x.sort() # Don't do this!
>>> print(y)
None
鉴于sort修改x且不返回任何值,最终的结果是x是经过排序的,而y包含None。为实现前述
目标,正确的方式之一是先将y关联到x的副本,再对y进行排序,如下所示:
>>> x = [4, 6, 2, 1, 7, 9]
>>> y = x.copy()
>>> y.sort()
>>> x
[4, 6, 2, 1, 7, 9]
>>> y
[1, 2, 4, 6, 7, 9]
只是将x赋给y是不可行的,因为这样x和y将指向同一个列表。为获取排序后的列表的副本,
另一种方式是使用函数sorted。 sorted函数返回排序后的副本
>>> x = [4, 6, 2, 1, 7, 9]
>>> y = sorted(x)
>>> x
[4, 6, 2, 1, 7, 9]
>>> y
[1, 2, 4, 6, 7, 9]
12. 高级排序
方法sort接受两个可选参数:key和reverse。参数key类似于参数cmp:你将其设置为一个用于排序的函数。对于另一个关键字参数reverse,将其指定为一个真值(True或False),以指出是否要按相反的顺序对列表进行排序。
字符串
字符串基本操作
所有标准序列操作(索引、切片、乘法、成员资格检查、长度、最小值和最大值)都适用于字符串,但别忘了字符串是不可变的,因此所有的元素赋值和切片赋值都是非法的。
设置字符串的格式:完整版
基本思想是对字符串调用方法format,并提供要设置其格式的值
字符串方法
1、center
方法center通过在两边添加填充字符(默认为空格)让字符串居中。
2、find
方法find在字符串中查找子串。如果找到,就返回子串的第一个字符的索引,否则返回-1。
3、join
join是一个非常重要的字符串方法,其作用与split相反,用于合并序列的元素。
要将字符列表转换为字符串,可使用下面的表达式:
''.join(somelist)
其中somelist是要转换的列表。
>>> seq = [1, 2, 3, 4, 5]
>>> sep = '+'
>>> sep.join(seq) # 尝试合并一个数字列表
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: sequence item 0: expected string, int found
>>> seq = ['1', '2', '3', '4', '5']
>>> sep.join(seq) # 合并一个字符串列表
'1+2+3+4+5'
>>> dirs = '', 'usr', 'bin', 'env'
>>> '/'.join(dirs)
'/usr/bin/env'
>>> print('C:' + '\\'.join(dirs))
C:\usr\bin\env
如你所见,所合并序列的元素必须都是字符串。
4、lower()
方法lower返回字符串的小写版本。
5、replace
方法replace将指定子串都替换为另一个字符串,并返回替换后的结果。
>>> 'This is a test'.replace('is', 'eez')
'Theez eez a test'
6、split
split是一个非常重要的字符串方法,其作用与join相反,用于将字符串拆分为序列。
>>> '1+2+3+4+5'.split('+')
['1', '2', '3', '4', '5']
>>> '/usr/bin/env'.split('/')
['', 'usr', 'bin', 'env']
>>> 'Using the default'.split()
['Using', 'the', 'default']
7、strip
方法strip将字符串开头和末尾的空白(但不包括中间的空白)删除,并返回删除后的结果。
>>> ' internal whitespace is kept '.strip()
'internal whitespace is kept'
判断字符串是否满足特定的条件
很多字符串方法都以is打头,如isspace、isdigit和isupper,它们判断字符串是否具有特定
的性质(如包含的字符全为空白、数字或大写)。如果字符串具备特定的性质,这些方法就返回
True,否则返回False。
附录B:isalnum、isalpha、isdecimal、isdigit、isidentifier、islower、isnumeric、
isprintable、isspace、istitle、isupper。
字典
将两个列表合并转为字典
>>> lst1=['a','b','c']
>>> lst2=[1,2,3]
>>> dict1=dict(zip(lst1,lst2))
>>> dict1
{'a': 1, 'b': 2, 'c': 3}
>>> keys=['id','name','age']
>>> values=[[1,'gao',22],[2,'wang',22],[3,'liu',21]]
>>>
>>>
>>> a = [dict(zip(keys,values)) for row in keys] if keys else None
>>> a
[{'id': [1, 'gao', 22], 'name': [2, 'wang', 22], 'age': [3, 'liu', 21]}, {'id': [1, 'gao', 22], 'name': [2, 'wang', 22], 'age': [3, 'liu', 21]}, {'id': [1, 'gao', 22], 'name': [2, 'wang', 22], 'age': [3, 'liu', 21]}]
>>>
>>> a = [dict(zip(keys,row)) for row in values] if values else None
>>> a
[{'id': 1, 'name': 'gao', 'age': 22}, {'id': 2, 'name': 'wang', 'age': 22}, {'id': 3, 'name': 'liu', 'age': 21}]
字典方法
1、clear
方法clear删除所有的字典项,这种操作是就地执行的(就像list.sort一样),因此什么都不
返回(或者说返回None)。
>>> a={}
>>> a['name']='wayne'
>>> a['age']=24
>>> b=a
>>> a={}
>>> b
{'name': 'wayne', 'age': 24}
>>> a={}
>>> a['age']=24
>>> a['name']='wayne'
>>> b=a
>>> a.clear()
>>> b
{}
>>> a
{}
x和y最初都指向同一个字典。在第一个场景中,我通过将一个空字典赋
给x来“清空”它。这对y没有任何影响,它依然指向原来的字典。这种行为可能正是你想要的,
但要删除原来字典的所有元素,必须使用clear。如果这样做,y也将是空的,如第二个场景所示
2、copy
方法copy返回一个新字典,其包含的键值对与原来的字典相同(这个方法执行的是浅拷贝,
因为值本身是原件,而非副本)
深拷贝,即同时复制值及其包含的所有值,等等。为此,可使用模块copy中的函数deepcopy。
>>> d={}
>>> d['names'] = ['Alfred', 'Bertrand']
>>> d
{'names': ['Alfred', 'Bertrand']}
>>> c=d.copy ()
>>> dc=deepcopy(d)
>>> d['names'].append('Cdasd')
>>> c
{'names': ['Alfred', 'Bertrand', 'Cdasd']}
>>> dc
{'names': ['Alfred', 'Bertrand']}
3、fromkeys
fromkeys创建一个新字典,其中包含指定的键,且每个键对应的值都是None。
>>> {}.fromkeys(['name','age'])
{'name': None, 'age': None}
>>>
>>> dict.fromkeys(['name','age'],'-')
{'name': '-', 'age': '-'}
4、get
如果你试图访问字典中没有的项,将引发错误。
用get来访问不存在的键时,没有引发异常,而是返回None。你可指定“默认”值,这样将返回你指定的值而不是None。
>>> d = {}
>>> print(d['name'])
Traceback (most recent call last):
File "<stdin>", line 1, in ?
KeyError: 'name'
>>> d = {}
>>> print(d['name'])
Traceback (most recent call last):
File "<stdin>", line 1, in ?
KeyError: 'name'
5、items
方法items返回一个包含所有字典项的列表,其中每个元素都为(key, value)的形式。字典项在列表中的排列顺序不确定。
>>> d = {'name':'wayne','age':'24','gender':'male'}
>>> it=d.items()
>>> it
dict_items([('name', 'wayne'), ('age', '24'), ('gender', 'male')])
# 返回值属于一种名为字典视图的特殊类型
>>> ('name','wayne') in it
True
视图的一个特点是不复制,始终是底层字典的映射,即便修改了底层字典。
>>> d['name']='gao'
>>> ('name','wayne') in it
False
>>> d['name']='wayne'
>>> ('name','wayne') in it
True
6、keys()
方法keys返回一个字典视图,其中包含指定字典中的键。
>>> d.keys()
dict_keys(['name', 'age', 'gender'])
7、pop、popitem
方法pop可用于获取与指定键相关联的值,并将该键值对从字典中删除。
>>> d
{'name': 'wayne', 'age': '24', 'gender': 'male'}
>>> d.pop('gender')
'male'
>>> d
{'name': 'wayne', 'age': '24'}
popitem()类似于列表中的pop,但是popitem随机地弹出一个字典项,因为字典是无序地,没有最后一个元素的概念。
>>> d.popitem()
('age', '24')
>>> d
{'name': 'wayne'}
8、setdefault
方法setdefault有点像get,因为它也获取与指定键相关联的值,但除此之外,setdefault还在字典不包含指定的键时,在字典中添加指定的键值对。
>>> d={}
>>> d.setdefault('name','N/A')
'N/A'
>>> d
{'name': 'N/A'}
>>> d['name']='wayne'
>>> d.setdefault('name','N/A')
'wayne'
>>> d
{'name': 'wayne'}
指定的键不存在时,setdefault返回指定的值并相应地更新字典。如果指定的键存在,就返回其值,并保持字典不变。与get一样,值是可选的;如果没有指定,默认为None。
>>> d={}
>>> d.setdefault('name')
>>> d
{'name': None}
9、update
方法update使用一个字典中的项来更新另一个字典。
>>> d = {'name':'wayne','age':'24','gender':'male'}
>>> tmp = {'like':'sports'}
>>> d.update(tmp)
>>> d
{'name': 'wayne', 'age': '24', 'gender': 'male', 'like': 'sports'}
对于通过参数提供的字典,将其项添加到当前字典中。如果当前字典包含键相同的项,就替换它。
10、values
方法values返回一个由字典中的值组成的字典视图。不同于方法keys,方法values返回的视图可能包含重复的值。
>>> d
{'name': 'wayne', 'age': '24', 'gender': 'male', 'like': 'sports'}
>>> d.values
<built-in method values of dict object at 0x7fb5b879a2d0>
>>> d.values()
dict_values(['wayne', '24', 'male', 'sports'])
迭代工具
并行迭代
1、并行迭代工具内置函数zip
将两个序列“缝合”起来,并返回一个由元组组成的序列。返回值是一个适合迭代的对象,要查看其内
容,可使用list将其转换为列表。
>>> names = ['anne', 'beth', 'george', 'damon']
>>> ages = [12, 45, 32, 102]
>>> list(zip(names,ages))
[('anne', 12), ('beth', 45), ('george', 32), ('damon', 102)]
>>> for name, age in zip(names, ages):
... print(name, 'is', age, 'years old')
...
anne is 12 years old
beth is 45 years old
george is 32 years old
damon is 102 years old
函数zip可用于“缝合”任意数量的序列。需要指出的是,当序列的长度不同时,函数zip将在最短的序列用完后停止“缝合”。
迭代时获取索引
在迭代对象序列的同时获取当前对象的索引
>>>i = 0
>>> seq = ['one', 'two', 'three']
>>> for element in seq:
... print i, seq[i]
... i +=1
...
0 one
1 two
2 three
更有效的方法是在 for 循环使用 enumerate()
>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
... print i, element
...
0 one
1 two
2 three
反向迭代和排序后再迭代
reversed和sorted函数,可用于任何序列或可迭代的对象,且不就地修改对象,而是返回反转和排序后的版本。
>>> sorted([1,2,2,6,3,11,7,4])
[1, 2, 2, 3, 4, 6, 7, 11]
>>> reversed('nihao')
<reversed object at 0x7f28a2ab9ac8>
>>> list(reversed('nihao'))
['o', 'a', 'h', 'i', 'n']
>>> ''.join(reversed('nihao'))
'oahin'
sorted返回一个列表,而reversed像zip那样返回一个更神秘的可迭代对象。你无需关心这到底意味着什么,只管在for循环或join等方法中使用它,不会有任何问题。只是你不能对它执行索引或切片操作,也不能直接对它调用列表的方法。要执行这些操作,可先使用list对返回的对象进行转换。
列表推导式
列表推导是从其他列表创建列表的方式,类似于数学中的集合推导。列表推导的工作原理非常简单,有点类似于for循环。
列表推导式的执行顺序:各语句之间是嵌套关系,左边第二个语句是最外层,依次往右进一层,左边第一条语句是最后一层。
# 列表由range(10)内每个值的平方组成
>>> [ x * x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 打印10以内能被3整除的平方值
>>> [ x * x for x in range(10) if x % 3 == 0]
[0, 9, 36, 81]
# for嵌套
>>> [(x,y) for x in range(3) for y in range(3)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
# 同样的for嵌套实现上面列表推导式的功能
>>> result=[]
>>> for x in range(3):
... for y in range(3):
... result.append((x,y))
...
>>> result
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
方括号换成圆括号不能转换成元组推导。而是创建生成器。花括号可以来执行字典推导。
>>> squares = {i:"{} square is {}".format(i,i**2) for i in range(10)}
>>> squares
{0: '0 square is 0', 1: '1 square is 1', 2: '2 square is 4', 3: '3 square is 9', 4: '4 square is 16', 5: '5 square is 25', 6: '6 square is 36', 7: '7 square is 49', 8: '8 square is 64', 9: '9 square is 81'}
在列表推导中,for前面只有一个表达式,而在字典推导中,for前面有两个用冒号分隔的表达式。这两个表达式分别为键及其对应的值。
三条语句:pass、del和exec
1、使用pass进行占位,这行代码什么都不做。
2、使用del 删除
对于你不再使用的对象,Python通常会将其删除(因为没有任何变量或数据结构成员指向它)。
>>> d = {'name':'wayne','age':'24','gender':'male'}
>>> dd=d
>>> d
{'name': 'wayne', 'age': '24', 'gender': 'male'}
>>> dd
{'name': 'wayne', 'age': '24', 'gender': 'male'}
>>> d=None
>>> dd
{'name': 'wayne', 'age': '24', 'gender': 'male'}
>>> dd=None
>>> d
>>> dd
最初d和dd指向同一个字典,将None赋值给d后,依然可以通过dd来访问这个字典。然而将dd也赋值为None后,这个字典就漂浮在计算机内存中,没有任何名称与之关联,就再也无法获取使用它了。因此,Python解释器直接将其删除。这被称为垃圾回收。请注意,在前面的代码中,也可将其他任何值(而不是None)赋给两个变量,这样字典也将消失。
使用del不仅会删除到对象的引用,还会删除名称本身。
>>> a=1
>>> del a
>>> a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
x和y指向同一个列表:
>>> x = ["Hello", "world"]
>>> y = x
>>> y[1] = "Python"
>>> x
['Hello', 'Python']
你可能认为通过删除x,也将删除y,但情况并非如此。
>>> del x
>>> y
['Hello', 'Python']
x和y指向同一个列表,但删除x对y没有任何影响,因为只删除名称x,而没有删除列表本身。
事实python根本没有办法删除值,Python解释器会立即删除不再使用的值。
3、使用exec 和eval 执行字符串及计算其结果
函数exec将字符串作为代码执行。
# 只提供一个参数,没有变量命名空间会污染命名空间,修改变量。
>>> from math import sqrt
>>> exec("sqrt=1")
>>> sqrt(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
添加第二个参数——字典,用作代码字符串的命名空间。
>>> from math import sqrt
>>> scope={}
>>> exec('sqrt=1',scope)
>>> sqrt(4)
2.0
>>> scope['sqrt']
1
可能带来破坏的代码并非覆盖函数sqrt。函数sqrt该怎样还怎样,而通过exec执行赋值语句创建的变量位于scope中。
将scope打印出来,将发现它包含很多内容,这是因为自动在其中添加了包含所有内置函数和值的字典builtins。
>>> len(scope)
2
>>> scope.keys()
dict_keys(['__builtins__', 'sqrt'])
eval是一个类似于exec的内置函数
exec执行一系列Python语句,而eval计算用字符串表示的Python表达式的值,并返回结果(exec什么都不返回,因为它本身是条语句)。
>>> scope = {}
>>> scope['x'] = 2
>>> scope['y'] = 3
>>> eval('x * y', scope)
6