第 4 章 介绍 Python 对象类型
Python 知识结构
程序由模块构成
模块包含语句
语句包含表达式
表达式创建并处理对象
为什么要使用内置类型
容易编写,可扩展,往往效率高,是语言标准的一部分。
Python 核心数据类型
数字、字符串、列表、字典、元组、文件、集合
其他核心类型:类型、None、布尔型
程序单元类型:函数、模块、类
Python 实现相关类型:已编译代码、调用栈跟踪
Python 是动态类型的强类型语言。
数字
整数
浮点数
复数
固定精度的十进制数
有理分数
Python 中 **
表示幂。Python 的整数类型会在需要时自动提升精度。
字符串
字符串用来记录文本信息和任意的字节集合。
字符串是由单字符组成的序列。
序列操作
s = 'spam'
len(s) # 长度 4
s[0] # 's'
s[-1] # 反向索引 'm' 一般来说相当于 s[len(s) - 1]
分片操作
s[1:3] # 'pa'
s[l:r]
相当于取出下标为 [l, r)
的内容。
s[1:] # 'pam'
s[:3] # 'spa'
s[:-1] # 'spa'
s[:] # 'spam' 一个 s 的 top-level copy
字符串支持使用 +
进行拼接和使用 *
进行重复
s + 'xyz' # 'spamxyz'
s * 3 # 'spamspamspam'
不可变性
注意 Python 中的字符串具有不可变性,每个操作的结果都会创建新的字符串。
我们可以把字符串转化为 list 或 bytearray。
L = list(s)
L[1] = 'c'
S = ''.join(L)
B = bytearray(b'spam') # 只适用于至多 8 位宽的文本
B.extend(b'eggs')
B.decode() # 转化为字符串
特定类型的方法
s.find('pa') # 1
s.find('ss') # -1 找不到
s.replace('pa', 'XYZ') # 'sXYZm' 会生成新对象
拆分字符串
line = 'aa,bbb,cc'
line.split(',') # ['aa', 'bbb', 'cc']
s.upper() # 'SPAM'
s.isalpha() # True
line = 'aa\n'
line.rstrip() # 'aa'
line.rstrip().split(',')
注意最后一个语句,Python 遵循从左到右的执行顺序。
格式化替换
'%s, %s' % ('a', 'b') # 'a, b' formatting expression
'{0}, {1}'.format('a', 'b') # formatting method
'{}, {}'.format('a', 'b')
后面会介绍更复杂的格式化方式。
寻求帮助
可以用 dir
列出所有支持的操作,再用 help
查询文档
dir(s)
help(s.replace)
字符串编程的其他方式
Python 字符串可以包裹在单引号或双引号,并让另一种可以作为字符串内容出现。也允许三引号(三个单引号或双引号)中包括多行字符串字面量。
交互中不可打印字符会输出为转义的形式。
Python 也支持原始(raw)字符串字面量,在引号前加 r
。
Unicode 字符串
3.X 版本后普通字符串是 Unicode
b'aaa' # bytes string
u'aaa' # Unicode
s.encode('utf8')
s.encode('utf16')
模式匹配
import re
列表
序列操作
支持所有之前字符串上的序列操作
特定的操作
列表元素没有特定类型约束。
L.append('a')
L.pop(idx) # 会返回 idx 上的元素并从列表中删掉
L.sort() # 列表排序,inplace
L.reverse() # 翻转 inplace
边界检查
Python 有边界检查
嵌套
Python 核心数据类型支持任意嵌套,即 list 中可以嵌套任意层 list。
推导
列表推导表达式 list comprehension expression
取出矩阵第二列
M = [[11, 12, 13], [21, 22, 23], [31, 32, 33]]
col2 = [row[1] for row in M]
更复杂的操作见后。
列表推导也会被用于集合、字典、生成器。
字典
字典是一种映射 mapping
。
映射操作
D = {'a' : 1, 'b' : 'bbb', 'c': 's'}
D = {} # 空字典
D['d'] = 'hhh' # create keys by assign
D = dict(name='Bob', job='dev', age=40) # 相当于 {'name': 'Bob', 'job': 'dev', 'age':40}
D = dict(zip(['name', 'job', 'age'], ['Bob', 'dev', 40]))
字典中的元素是无序的。
重访嵌套
字典值也可以嵌套字典或其他数据类型。
Python 会自动管理内存,具有垃圾回收机制。
不存在的键:if 测试
if some_key in D:
# do some thing
if not some_key in D:
# do some thing
我们也可以使用带初始值的 get
value = D.get('key', default_val)
键的排序:for 循环
keys = list(D.keys())
keys.sort()
for key in keys:
print(key, '=>', D[key])
或者
for key in sorted(D):
print(key, '=>', D[key])
迭代和优化
for 循环看起来很像列表推导表达式,他们都是通用迭代工具。他们能工作于任何的遵守迭代协议的任意可迭代对象。
列表推导和相关的函数编程工具,在某些代码运行得比 for 循环更快。
元组
tuple
。
元组是一个不可变的序列。
特有的方法
t.index(item) # 查找 item 出现的下标
t.count(item) # 查找 item 出现的次数
只有一个元素
t = (1,)
文件
f = open('/file/path/file.txt') # 默认以读 'r' 模式打开文件
text = f.read() # 读整个文件到 text
f = open('/file/path/file.txt', 'w') # 写模式打开文件
f.write('Hello, world\n')
使用迭代器
for line in open('file.txt'):
print(line)
二进制字节文件
import struct
packed = struct.pack('>i4sh', 7, b'spam', 8)
file = open('data.bin', 'wb')
file.write(packed) # 10
file.close()
data = open('data.bin', 'rb').read()
print(struct.unpack('>i4sh', data)) # (7, b'spam', 8)
Unicode 文本文件
S = 'sp\xc4m'
file = open('unidata.txt', 'w', encoding = 'utf-8')
file.write(S) # 4 characters written
file.close()
text = open('unidata.txt', encoding = 'utf-8').read()
print(len(text)) # 4
raw = open('unidata.txt', 'rb').read()
print(len(raw)) # 5
其他类文件工具
Python 还有一些类文件工具:管道,FIFO,套接字,按键值访问的文件,持久化对象 shelve,基于描述符的文件,关系型数据库接口和面向对象数据库接口等。
其他核心类型
集合 set
X = set('spam')
Y = {'h', 'a', 'm'}
X & Y # intersection
X | Y # union
X - Y # difference
X > Y # super set
ps = {n ** 2 for n in [1, 2, 3, 4]}
'p' in set('spam')
十进制数(固定精度浮点数)和分数
import decimal
from fractions import Fraction
布尔值
True
False
特殊的占位符对象
None
如何破坏代码的灵活性
内置函数 type 可以返回对象类型。在 Python 3.X 中类型已经完全和类合并起来了。
检查类型
L = []
if type(L) == type([]):
print('yes')
if type(L) == list:
print('yes')
if isinstance(L, list):
print('yes')
用户定义的类
后面章节详细展开。
剩余的内容
Python 的每一样东西都是对象,但这不意味着一定要做面向对象的编程。
Next: [算法][图论] Vizing 定理