《Learning Python》 笔记 第 4 章 介绍 Python 对象类型
Notes Learning Python
Lastmod: 2024-07-14 周日 22:44:06

第 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 的每一样东西都是对象,但这不意味着一定要做面向对象的编程。

Prev: [算法][DP] 高维前缀和 SOS DP
Next: [算法][图论] Vizing 定理