8. 基本数据类型
8.1. 类型与方法
8.1.1. str
索引、切片:[ind];[first:last] 获取区间 [first, last) 内的元素。
长度:len
查找:若字符/序列不在字符串内,index 抛出异常
ValueError
;find 返回 -1。判断字符串内容:字母,isalpha();数字,isdigit();数字或字母,isalnum();大小写,isupper(),islower()。
大小写转换:capitalize()、lower()、upper()。
获取字符 ASCII 码:ord(c)
根据 ASCII 码转换为字符:chr(n),ASCII 码在 0 到 255 之间。
判断开头结尾:startswith、endswith。
连接:join,将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串。
分割:split、partition。 如果想把字符串分割成独立的字符,用 list(string)。
替代:replace
清除空白: strip、lstrip、rstrip
1>>> s = "abcde" 2>>> "-".join(s) 3a-b-c-d-e 4>>> s = ['abc', 'def', 'ghi'] 5>>> "-".join(s) 6abc_def_ghi 7>>> s 8['abc', 'def', 'ghi'] 9 10>>> s = "a-b-c-d-e" 11>>> s.partion('-') ## 只能分割为3部分 12('a', '-', 'b-c-d-e') 13>>> s.split('-') 14['a', 'b', 'c', 'd', 'e'] 15>>> s 16"a-b-c-d-e"Warning
str 是不可变对象,其所有方法都 不改变对象本身 ,而是返回所创建的新对象。
8.1.2. tuple
索引、切片:[ind];[first:last] 获取区间 [first, last) 内的元素。
元组的元素不可改变,类似于常量类型。
collections.namedtuple :构造一个带字段名的元组,可以通过索引、切片或属性名称进行访问。:
collections.namedtuple(typename, field_names, verbose=False, rename=False)1>>> from collections import namedtuple 2>>> User = namedtuple('User', ['name', 'age', 'id']) ## 或 User = namedtuple('User', 'name age id') 3>>> user = User(name='tester', age='22', id='464643123') ## 或 user = User('tester', '22', '464643123') 4>>> user 5User(name='tester', age='22', id='464643123') 6>>> user._fields 7('name', 'age', 'id') 8>>> user.name 9'tester' 10 11## 使用 _replace 修改属性,返回新的对象 12>>> user._replace(age='12') 13User(name='tester', age='12', id='464643123') 14 15## 使用 _asdict 将元组转换为有序字典 16>>> user._asdict() 17OrderedDict([('name', 'tester'), ('age', '22'), ('id', '464643123')]) 18 19## 使用 _make 用列表构造元组 20>>> user = User._make(['fong', 25, '000000000']) 21>>> user 22User(name='fong', age=25, id='000000000') 23>>> user[:2] 24('fong', 25)
8.1.3. list
索引、切片:[ind];[first:last] 获取区间 [first, last) 内的元素。
统计元素出现的次数:count
追加:append
拓展:extend
插入:insert
弹出元素:pop,默认弹出列表末尾的元素
清空:clear()
移除/删除元素:remove,del (del可删除切片)
排序:sort
逆序:reverse
1>>> a = [1,2,3] 2>>> a.append(4) 3>>> a 4[1, 2, 3, 4] 5>>> a.extend([10,20,30]) 6>>> a 7[1, 2, 3, 4, 10, 20, 30] 8 9>>> a.insert(1, 5) ## 在第一个元素之后插入 10>>> a 11[1, 5, 2, 3, 4, 10, 20, 30] 12 13>>> a.remove(2) 14>>> a 15[1, 5, 3, 4, 10, 20, 30] 16>>> del a[3] 17>>> a 18[1, 5, 3, 10, 20, 30] 19 20>>> a.sort(reverse=True) 21>>> a 22[30, 20, 10, 5, 3, 1] ## 直接修改 a,无返回值。使用 sorted 返回排序后的副本。 23 24>>> a2 = a.pop(2) 25>>> a2 2610 27>>> a 28[30, 20, 5, 3, 1]
Note
对于 切片(slice)
操作,下标越界 不会 报错,返回空。
对于 索引(index)
操作,下标越界 会 报错。
s[i:j]
The slice of s from i to j is defined as the sequence of items with index k such that i <= k < j.
If i or j is greater than len(s), use len(s).
If i is omitted or None, use 0.
If j is omitted or None, use len(s).
If i is greater than or equal to j, the slice is empty.
s[i:j:-1]
- 当 i 省略,默认使用 len(s)。
- 当 j 省略,输出 s[0:i+1] 的逆序。
- 当 j = -1,默认使用 len(s),会输出空列表。注意,这里不等同于 s[i::-1]。
- s[::-1] 是 s 的逆序。
8.1.4. dict
获取:keys(),values(),items()。在 Python3 中返回的不再是列表,而是 dict_keys、dict_values、dict_items,需要手动转换为列表。
清空:clear()
删除:pop(key),返回健对应的值,并删除键所对应的键值对。
访问:get(key),不存在时返回 None。
更新:update(d),把另一个字典 d 中的项添加到当前字典。
浅复制:copy()
1>>> info ={ 2... "name":"Tom", 3... "age":25, 4... "sex":"man", 5... } 6>>> info.keys() 7['age', 'name', 'sex'] 8>>> info.values() 9[25, 'Tom', 'man'] 10>>> info.items() 11[('age', 25), ('name', 'Tom'), ('sex', 'man')] 12 13>>> info.get(age) 1425 15>>> new = {"weight": 60} 16>>> info.update(new) 17>>> info 18{'age': 25, 'name': 'Tom', 'weight': 60, 'sex': 'man'} 19>>> info.clear() 20>>> info 21{}
collections.OrderedDict :按关键字排序的字典。
collections.defaultdict :defaultdict 类使用一种给定数据类型来初始化。当所访问的 key 不存在的时候,会实例化一个 value 作为默认值。因此,判断某个 key 是否存在,应使用 get(key)。
1>>> from collections import defaultdict 2>>> dd = defaultdict(list) ## 使用 list 作为value type 3defaultdict(<type 'list'>, {}) 4>>> dd['a'] 5[] 6>>> dd['b'].append("hello") 7defaultdict(<type 'list'>, {'a': [], 'b': ['hello']})Warning
如果一个 defaultdict 必须包含给定的 key,则首先要 显式 地对所有的 key 进行访问和初始化。毕竟 defaultdict 只会为访问过的 key 关联一个默认值。
8.1.5. set
特征:无重复,无须,每个元素为不可变类型
增加元素:单个元素,add;多个元素,update
删除:删除元素不存在,remove 报错,discard 无反应。
清空:clear()
集合操作:&,|,-,^(交差补集,去除交集后剩下元素的并集),issubset 、isupperset。
1>>> s1 = {'a', 'b', 'c'} ## 或者 s1 = set(['a', 'b', 'c']) 2>>> s1.update({'e','d'}) 3>>> s1 4set(['a', 'c', 'b', 'e', 'd'])
8.2. 深复制和浅复制
直接赋值 :并没有拷贝对象,而是拷贝了对象的引用,因此原始对象或被赋值对象的改变,都会导致另一个对象被修改。
1>>> alist = [1,2,3] 2>>> b = alist ## 引用 3>>> c = alist[:] ## 复制 4>>> alist.append(5) 5>>> alist 6[1, 2, 3, 5] 7>>> b 8[1, 2, 3, 5] 9>>> c 10[1, 2, 3] 11>>> b[0] = -1 12>>> a 13[-1, 2, 3, 5] 14>>> b 15[-1, 2, 3, 5] 16>>> c 17[1, 2, 3]
浅复制 :只会复制父对象,而不会复制对象的内部的子对象。
1>>> from copy import copy 2>>> alist = [1,2,3,['a','b']] ## ['a','b'] 是列表,是一个子对象 3>>> a_copy = copy(alist) ## dict类有copy()方法,e.g.,d.copy() 4>>> alist.append(5) ## 非子对象的修改 5>>> alist 6[1, 2, 3, ['a', 'b'], 5] 7>>> a_copy 8[1, 2, 3, ['a', 'b']] 9>>> a_copy[0] = -1 10>>> alist 11[1, 2, 3, ['a', 'b'], 5] 12>>> a_copy 13[-1, 2, 3, ['a', 'b']] 14 15>>> alist[3].append('c') ## 子对象的修改 16>>> alist 17[1, 2, 3, ['a', 'b', 'c'], 5] 18>>> a_copy 19[-1, 2, 3, ['a', 'b', 'c']] 20>>> a_copy[3].append('d') 21>>> alist 22[1, 2, 3, ['a', 'b', 'c', 'd'], 5] 23>>> a_copy 24[-1, 2, 3, ['a', 'b', 'c', 'd']]
深复制 :复制对象及其子对象,原始对象的改变不会造成深复制里任何子元素的改变。
1>>> from copy import deepcopy 2>>> alist = [1,2,3,['a','b']] ## ['a','b'] 是列表,是一个子对象 3>>> a_copy = deepcopy(alist) 4>>> alist[3].append('c') ## 子对象的修改 5>>> alist 6[1, 2, 3, ['a', 'b', 'c']] 7>>> a_copy 8[1, 2, 3, ['a', 'b']] 9>>> a_copy[3].append('d') 10>>> alist 11[1, 2, 3, ['a', 'b', 'c']] 12>>> a_copy 13[1, 2, 3, ['a', 'b', 'd']]
Note
对于可变对象 dict 和 list 、 set ,需要暂存临时对象或者作为函数参数传递时,如果不希望对象被更改,都需要使用深复制。
8.3. 再谈可变对象与不可变对象
第一章和第十五章提到可变对象与不可变对象。
dict 和 set 的底层实现都是 哈希表 。哈希要求key唯一,因此 dict 和 set 的key都要求是 不可变对象 。
1>>> x = 'abcd'
2>>> id(x)
3317860320L
4>>> x += 'efg'
5>>> id(x)
6317859200L
7>>> x = 1
8>>> id(x)
931429240L
10>>> x += 2
11>>> id(x)
1231429192L
13## x 的加法运算生成了一个新的对象,而不是对原对象的改变
14
15>>> a = [5, 3, 4, 3]
16>>> id(a)
17314009096L
18>>> b = [5, 3, 4, 3] ## b = a[:]
19>>> id(b)
20314011080L
21## a 和 b 的 id 不同,尽管值相同
22>>> b.append(1)
23>>> b
24[5, 3, 4, 3, 1]
25>>> id(b)
26314011080L
27## 改变 b,仍然是同一个对象,因此是可变对象
8.4. 参考资料
Python基本数据类型
切片python字符串时 为何不会引起下标越界?
python中defaultdict方法的使用
python的复制,深拷贝和浅拷贝的区别
Python学习日记之字典深复制与浅复制
Python namedtuple