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

 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]

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'])

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.

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

对于可变对象 dictlistset ,需要暂存临时对象或者作为函数参数传递时,如果不希望对象被更改,都需要使用深复制。

8.3. 再谈可变对象与不可变对象

第一章和第十五章提到可变对象与不可变对象。

dictset 的底层实现都是 哈希表 。哈希要求key唯一,因此 dictset 的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. 参考资料

  1. Python基本数据类型

  1. 切片python字符串时 为何不会引起下标越界?

  1. python中defaultdict方法的使用

  1. python的复制,深拷贝和浅拷贝的区别

  1. Python学习日记之字典深复制与浅复制

  1. Python namedtuple