In [9]: tup =tuple(['foo', [1, 2], True])In [10]: tup[2]=False---------------------------------------------------------------------------TypeErrorTraceback (most recent call last)<ipython-input-10-c7308343b841>in<module>()---->1 tup[2]=FalseTypeError:'tuple'object does not support item assignment
如果元组中的某个对象是可变的,比如列表,可以在原位进行修改:
In [11]: tup[1].append(3)In [12]: tupOut[12]: ('foo', [1,2,3],True)
可以用加号运算符将元组串联起来:
In [13]: (4,None,'foo') + (6,0) + ('bar',)Out[13]: (4,None,'foo',6,0,'bar')
元组乘以一个整数,像列表一样,会将几个元组的复制串联起来:
In [14]: ('foo','bar') *4Out[14]: ('foo','bar','foo','bar','foo','bar','foo','bar')
对象本身并没有被复制,只是引用了它。
拆分元组
如果你想将元组赋值给类似元组的变量,Python会试图拆分等号右边的值:
In [15]: tup = (4,5,6)In [16]: a, b, c = tupIn [17]: bOut[17]:5
即使含有元组的元组也会被拆分:
In [18]: tup =4,5, (6,7)In [19]: a, b, (c, d) = tupIn [20]: dOut[20]:7
使用这个功能,你可以很容易地替换变量的名字,其它语言可能是这样:
tmp = aa = bb = tmp
但是在Python中,替换可以这样做:
In [21]: a, b =1,2In [22]: aOut[22]:1In [23]: bOut[23]:2In [24]: b, a = a, bIn [25]: aOut[25]:2In [26]: bOut[26]:1
变量拆分常用来迭代元组或列表序列:
In [27]: seq = [(1,2,3), (4,5,6), (7,8,9)]In [28]:for a, b, c in seq: ....:print('a={0}, b={1}, c={2}'.format(a, b, c))a=1, b=2, c=3a=4, b=5, c=6a=7, b=8, c=9
In [123]: words = ['apple', 'bat', 'bar', 'atom', 'book']
In [124]: by_letter = {}
In [125]: for word in words:
.....: letter = word[0]
.....: if letter not in by_letter:
.....: by_letter[letter] = [word]
.....: else:
.....: by_letter[letter].append(word)
.....:
In [126]: by_letter
Out[126]: {'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book']}
setdefault方法就正是干这个的。前面的for循环可以改写为:
for word in words:
letter = word[0]
by_letter.setdefault(letter, []).append(word)
In [141]: c = a.copy()
In [142]: c |= b
In [143]: c
Out[143]: {1, 2, 3, 4, 5, 6, 7, 8}
In [144]: d = a.copy()
In [145]: d &= b
In [146]: d
Out[146]: {3, 4, 5}
与字典类似,集合元素通常都是不可变的。要获得类似列表的元素,必须转换成元组:
In [147]: my_data = [1, 2, 3, 4]
In [148]: my_set = {tuple(my_data)}
In [149]: my_set
Out[149]: {(1, 2, 3, 4)}
你还可以检测一个集合是否是另一个集合的子集或父集:
In [150]: a_set = {1, 2, 3, 4, 5}
In [151]: {1, 2, 3}.issubset(a_set)
Out[151]: True
In [152]: a_set.issuperset({1, 2, 3})
Out[152]: True
In [154]: strings = ['a', 'as', 'bat', 'car', 'dove', 'python']
In [155]: [x.upper() for x in strings if len(x) > 2]
Out[155]: ['BAT', 'CAR', 'DOVE', 'PYTHON']
用相似的方法,还可以推导集合和字典。字典的推导式如下所示:
dict_comp = {key-expr : value-expr for value in collection if condition}
集合的推导式与列表很像,只不过用的是尖括号:
set_comp = {expr for value in collection if condition}
In [156]: unique_lengths = {len(x) for x in strings}
In [157]: unique_lengths
Out[157]: {1, 2, 3, 4, 6}
map函数可以进一步简化:
In [158]: set(map(len, strings))
Out[158]: {1, 2, 3, 4, 6}
作为一个字典推导式的例子,我们可以创建一个字符串的查找映射表以确定它在列表中的位置:
In [159]: loc_mapping = {val : index for index, val in enumerate(strings)}
In [160]: loc_mapping
Out[160]: {'a': 0, 'as': 1, 'bat': 2, 'car': 3, 'dove': 4, 'python': 5}
In [164]: some_tuples = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
In [165]: flattened = [x for tup in some_tuples for x in tup]
In [166]: flattened
Out[166]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
记住,for表达式的顺序是与嵌套for循环的顺序一样(而不是列表推导式的顺序):
flattened = []
for tup in some_tuples:
for x in tup:
flattened.append(x)
import re
def clean_strings(strings):
result = []
for value in strings:
value = value.strip()
value = re.sub('[!#?]', '', value)
value = value.title()
result.append(value)
return result
def remove_punctuation(value):
return re.sub('[!#?]', '', value)
clean_ops = [str.strip, remove_punctuation, str.title]
def clean_strings(strings, ops):
result = []
for value in strings:
for function in ops:
value = function(value)
result.append(value)
return result
In [193]: import itertools
In [194]: first_letter = lambda x: x[0]
In [195]: names = ['Alan', 'Adam', 'Wes', 'Will', 'Albert', 'Steven']
In [196]: for letter, names in itertools.groupby(names, first_letter):
.....: print(letter, list(names)) # names is a generator
A ['Alan', 'Adam']
W ['Wes', 'Will']
A ['Albert']
S ['Steven']
In [197]: float('1.2345')
Out[197]: 1.2345
In [198]: float('something')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-198-439904410854> in <module>()
----> 1 float('something')
ValueError: could not convert string to float: 'something'
def attempt_float(x):
try:
return float(x)
except:
return x
当float(x)抛出异常时,才会执行except的部分:
In [200]: attempt_float('1.2345')
Out[200]: 1.2345
In [201]: attempt_float('something')
Out[201]: 'something'
你可能注意到float抛出的异常不仅是ValueError:
In [202]: float((1, 2))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-202-842079ebb635> in <module>()
----> 1 float((1, 2))
TypeError: float() argument must be a string or a number, not 'tuple'
def attempt_float(x):
try:
return float(x)
except ValueError:
return x
然后有:
In [204]: attempt_float((1, 2))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-204-9bdfd730cead> in <module>()
----> 1 attempt_float((1, 2))
<ipython-input-203-3e06b8379b6b> in attempt_float(x)
1 def attempt_float(x):
2 try:
----> 3 return float(x)
4 except ValueError:
5 return x
TypeError: float() argument must be a string or a number, not 'tuple'
可以用元组包含多个异常:
def attempt_float(x):
try:
return float(x)
except (TypeError, ValueError):
return x
In [209]: lines = [x.rstrip() for x in open(path)]
In [210]: lines
Out[210]:
['Sueña el rico en su riqueza,',
'que más cuidados le ofrece;',
'',
'sueña el pobre que padece',
'su miseria y su pobreza;',
'',
'sueña el que a medrar empieza,',
'sueña el que afana y pretende,',
'sueña el que agravia y ofende,',
'',
'y en el mundo, en conclusión,',
'todos sueñan lo que son,',
'aunque ninguno lo entiende.',
'']
如果使用open创建文件对象,一定要用close关闭它。关闭文件可以返回操作系统资源:
In [211]: f.close()
用with语句可以可以更容易地清理打开的文件:
In [212]: with open(path) as f:
.....: lines = [x.rstrip() for x in f]
In [213]: f = open(path)
In [214]: f.read(10)
Out[214]: 'Sueña el r'
In [215]: f2 = open(path, 'rb') # Binary mode
In [216]: f2.read(10)
Out[216]: b'Sue\xc3\xb1a el '
read模式会将文件句柄的位置提前,提前的数量是读取的字节数。tell可以给出当前的位置:
In [217]: f.tell()
Out[217]: 11
In [218]: f2.tell()
Out[218]: 10
In [225]: with open('tmp.txt', 'w') as handle:
.....: handle.writelines(x for x in open(path) if len(x) > 1)
In [226]: with open('tmp.txt') as f:
.....: lines = f.readlines()
In [227]: lines
Out[227]:
['Sueña el rico en su riqueza,\n',
'que más cuidados le ofrece;\n',
'sueña el pobre que padece\n',
'su miseria y su pobreza;\n',
'sueña el que a medrar empieza,\n',
'sueña el que afana y pretende,\n',
'sueña el que agravia y ofende,\n',
'y en el mundo, en conclusión,\n',
'todos sueñan lo que son,\n',
'aunque ninguno lo entiende.\n']
In [234]: data.decode('utf8')
Out[234]: 'Sueña el '
In [235]: data[:4].decode('utf8')
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
<ipython-input-235-300e0af10bb7> in <module>()
----> 1 data[:4].decode('utf8')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc3 in position 3: unexpecte
d end of data
文本模式结合了open的编码选项,提供了一种更方便的方法将Unicode转换为另一种编码:
In [236]: sink_path = 'sink.txt'
In [237]: with open(path) as source:
.....: with open(sink_path, 'xt', encoding='iso-8859-1') as sink:
.....: sink.write(source.read())
In [238]: with open(sink_path, encoding='iso-8859-1') as f:
.....: print(f.read(10))
Sueña el r
In [240]: f = open(path)
In [241]: f.read(5)
Out[241]: 'Sueña'
In [242]: f.seek(4)
Out[242]: 4
In [243]: f.read(1)
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
<ipython-input-243-7841103e33f5> in <module>()
----> 1 f.read(1)
/miniconda/envs/book-env/lib/python3.6/codecs.py in decode(self, input, final)
319 # decode input (taking the buffer into account)
320 data = self.buffer + input
--> 321 (result, consumed) = self._buffer_decode(data, self.errors, final
)
322 # keep undecoded input until the next call
323 self.buffer = data[consumed:]
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb1 in position 0: invalid s
tart byte
In [244]: f.close()