Python 3 入门 - 5. 内置数据类型

介绍Python中内置的基本数据类型,包括数字类型及浮点计算的问题、序列类型(rangelisttuplestrbytesbytearray)、容器类型(frozensetset)、映射类型(dict)和枚举类型(Enum)。


主要内置类型继承关系

下图展示了python主要内置类型的继承关系。int 是数字类型,bool 继承自int。非数字类型主要包括 SequenceSetMapping 三大类,这三类数据类型中,MutableXXX 的子类是可变类型,即该类型对象可以被修改,而其他子类的对象为只读,不能被修改。
在这里插入图片描述


数字类型

内置三种基本数字类型: 整数, 浮点数复数。标准库还包含附加的数字类型:分数Decimal
具体参考官方文档:https://docs.python.org/zh-cn/3/library/stdtypes.html#numeric-types-int-float-complex

这里重点记录一下 浮点计算 需要注意的问题和解决方案。

浮点计算的问题

关于浮点数问题的详细介绍可参考: 浮点算术:争议和限制

举个例子:

>>> 0.1 + 0.1 + 0.1 == 0.3
False

对 0.1 进行舍入之后再计算:

>>> round(0.1, 1)
0.1
>>> round(0.1, 1) + round(0.1, 1) + round(0.1, 1) == 0.3
False
>>> round(0.1, 1) + round(0.1, 1) + round(0.1, 1)
0.30000000000000004
>>> round(0.1 + 0.1 + 0.1, 1) == 0.3
True

另外,python 3 中的 round() 方法已经不再像 python 2 那样是“四舍五入”,而是“四舍六入五成双”,即:

  • 5后不为0时,舍5进1
  • 5后为0时,看5前面的数字,奇进偶不进
>>> for x in range(10):
...     print('round(%d.5): ' %x, round(x+0.5))
...
round(0.5):  0
round(1.5):  2
round(2.5):  2
round(3.5):  4
round(4.5):  4
round(5.5):  6
round(6.5):  6
round(7.5):  8
round(8.5):  8
round(9.5):  10
>>> for x in range(10):
...     print('round(%d.51): ' %x, round(x+0.51))
...
round(0.51):  1
round(1.51):  2
round(2.51):  3
round(3.51):  4
round(4.51):  5
round(5.51):  6
round(6.51):  7
round(7.51):  8
round(8.51):  9
round(9.51):  10

使用 Decimal 类型

如果要进行精确计算,并且要实现 “四舍五入”,就需要使用 Decimal 类型了。下面代码演示了 Decimal的基本用法,详细说明参考:十进制定点和浮点运算

from decimal import Decimal as D, InvalidOperation
from decimal import DefaultContext, ROUND_HALF_UP, setcontext

# Set applicationwide defaults 
# for all threads about to be launched
DefaultContext.prec = 10                  # 10位精度(有效数字,默认值是28)
DefaultContext.rounding = ROUND_HALF_UP   # 舍入模式为四舍五入(默认值是 ROUND_HALF_EVEN)
setcontext(DefaultContext)


# 小数位数
ZERODIGITS = D('1')
TWODIGITS = D('0.01')
FOURDIGITS = D('0.0001')

def calc(x, op='+', y=0):
    # 计算过程保留4位小数
    d1 = D(x).quantize(FOURDIGITS)
    d2 = D(y).quantize(FOURDIGITS)

    operates = {
        '+': lambda a, b: a + b,
        '-': lambda a, b: a - b,
        '*': lambda a, b: a * b,
        '/': lambda a, b: a / b,
    }

    return operates[op](d1, d2)


print('-' * 40)
print(calc(0.1, '+', 1/3))
print(calc(1/3, '-', 1/7))
print(calc(100000.1, '*', 3))

# 精度超限(因计算过程保留4位小数,此处有效数字达到11位)
try:
    print(calc(1000000.1, '*', 3))
except InvalidOperation as e:
    print(repr(e))

print(calc(0.2, '/', 3))
print(calc(0.2, '/', 3).quantize(FOURDIGITS))

print('-' * 40)
for x in range(6):
    # 结果保留2位小数
    print(calc(x + 0.5).quantize(TWODIGITS))

print('-' * 40)
for x in range(6):
    # 结果保留0位小数
    print(calc(x + 0.5).quantize(ZERODIGITS))

运行结果:

----------------------------------------
0.4333
0.1904
300000.3000
InvalidOperation([<class 'decimal.InvalidOperation'>])
0.06666666667
0.0667
----------------------------------------
0.50
1.50
2.50
3.50
4.50
5.50
----------------------------------------
1
2
3
4
5
6

序列类型

序列类型Sequence 的子类。主要包括 rangelisttuplestrbytesbytearray

所有 Sequence 类型都支持的操作

在表格中,st 是具有相同类型的序列n, i, jk 是整数而 x 是任何满足 s 所规定的类型和值限制的任意对象。

运算结果备注
x in s如果 s 中的某项等于 x 则结果为 True,否则为 False
x not in s如果 s 中的某项等于 x 则结果为 False,否则为 True
s + tst 相拼接
range 除外
拼接不可变序列总是会生成新的对象
s * n 或 n * s相当于 s 与自身进行 n 次拼接
range 除外
序列中的项不会被拷贝,它们会被多次引用
s[i]s 的第 i 项,起始为 0
s[i:j]s 从 i 到 j 的切片
s[i:j:k]s 从 i 到 j 步长为 k 的切片
len(s)s 的长度
min(s)s 的最小项
max(s)s 的最大项
s.index(x[, i[, j]])xs 中首次出现项的索引号(索引号在 i 或其后且在 j 之前)
range 不支持参数 i 和 j
s.count(x)xs 中出现的总次数

拼接不可变序列总是会生成新的对象。 这意味着通过重复拼接来构建序列的运行时开销将会基于序列总长度的乘方。想要获得线性的运行时开销,你必须改用下列替代方案之一:

  • 如果拼接 str 对象,你可以构建一个列表并在最后使用 str.join() 或是写入一个 io.StringIO 实例并在结束时获取它的值
  • 如果拼接 bytes 对象,你可以类似地使用 bytes.join()io.BytesIO,或者你也可以使用 bytearray 对象进行原地拼接。 bytearray 对象是可变的,并且具有高效的重分配机制
  • 如果拼接 tuple 对象,请改为扩展 list
  • 对于其它类型,请查看相应的文档

所有 MutableSequence 类型都支持的操作

表格中的 s可变序列类型的实例t 是任意 Iterable 对象,而 x 是符合对 s 所规定类型与值限制的任何对象。

运算结果备注
s[i] = xs 的第 i 项替换为 x
s[i:j] = ts 从 i 到 j 的切片替换为可迭代对象 t 的内容
del s[i:j]等同于 s[i:j] = []
s[i:j:k] = ts[i:j:k] 的元素替换为 t 的元素
s.append(x)x 添加到序列的末尾 (等同于 s[len(s):len(s)] = [x])
s.clear()s 中移除所有项 (等同于 del s[:])
s.copy()创建 s 的浅拷贝 (等同于 s[:])
浅拷贝 指的是重新分配一块内存,创建一个新的对象,
但里面的元素是原对象中各个子对象的引用。
s.extend(t) 或 s += tt 的内容扩展 s (基本上等同于 s[len(s):len(s)] = t)
s *= n使用 s 的内容重复 n 次来对其进行更新
序列中的项不会被拷贝,它们会被多次引用
s.insert(i, x)在由 i 给出的索引位置将 x 插入 s (等同于 s[i:i] = [x])
s.pop() 或 s.pop(i)提取在 i 位置上的项,并将其从 s 中移除
s.remove(x)删除 s 中第一个 s[i] 等于 x 的项目。
s.reverse()就地将列表中的元素逆序。

范围(range)

range 类型表示 不可变 的数字序列,通常用于在 for 循环中循环指定的次数。以下是 range 的构造函数:

class range(stop)
class range(start, stop[, step])

>>> for x in range(10,15):
...     print(x)
...
10
11
12
13
14
>>> for x in range(5,15,3):
...     print(x)
...
5
8
11
14
>>>

元组(tuple)与列表(list)

tuplelist 是一对性质相似的类型。区别在于 tuple不可变序列,而 list可变序列

元组

tuple 的构造函数为:
class tuple([iterable])

可以用多种方式构建元组:

  • 使用一对圆括号来表示空元组: ()
  • 使用一个后缀的逗号来表示单元组: a, 或 (a,)
  • 使用以逗号分隔的多个项: a, b, c or (a, b, c)
  • 使用内置的 tuple(): tuple() 或 tuple(iterable)
>>> t = tuple(range(5))
>>> t
(0, 1, 2, 3, 4)
>>> t = 10, 20, 30    # 元组打包
>>> t
(10, 20, 30)
>>> a, b, c = t       # 序列解包,可以是其他序列类型
>>> a
10
>>> b
20
>>> c
30
>>> x, y, z = 1, 2, 3    # 多重赋值,其实只是元组打包和序列解包的组合
>>> x
1
>>> y
2
>>> z
3

列表

list 的构造函数为:
class list([iterable])

可以用多种方式构建列表:

  • 使用一对方括号来表示空列表: []
  • 使用方括号,其中的项以逗号分隔: [a], [a, b, c]
  • 使用列表推导式: [x for x in iterable]
  • 使用类型的构造器: list() 或 list(iterable)
>>> [x for x in (10,15,20) if x % 10 == 0]
[10, 20]
>>> [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

利用列表推导式实现矩阵转置:

>>> matrix = [
...   [1, 2, 3, 4],
...   [5, 6, 7, 8],
...   [9, 10, 11, 12],
... ]
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

以上代码等价于:

>>> lst = []
>>> for i in range(4):
...     newr = []
...     for r in matrix:
...         newr.append(r[i])
...     lst.append(newr)
...
>>> lst
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

list 除了支持前面提到的所有 SequenceMutableSequence 类型的操作,还额外提供 sort() 方法,此方法会对列表进行原地排序。insert()remove()sort() 等方法只修改列表,不输出返回值——返回的默认值为 None

虽然 tuple 是不可变序列, list 是可变序列,但是 tuple 的元素可以是 listlist 的元素也可以是 tuple),也就是说,当 tuple 的元素是可变类型时,其元素仍然是可以被修改的。

>>> t = (list(range(3)), [], ['hello'])
>>> t[1].extend([7,8,9])
>>> t
([0, 1, 2], [7, 8, 9], ['hello'])
>>> t[0].pop()
2
>>> t
([0, 1], [7, 8, 9], ['hello'])

tuplelist 中的元素可以是不同类型,例如:

>>> t = (10, 'cheese', [3,4])
>>> t
(10, 'cheese', [3, 4])
列表排序

1. 使用 sorted() 函数,不改变序列本身

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> sorted(basket)
['apple', 'apple', 'banana', 'orange', 'orange', 'pear']
>>> basket
['apple', 'orange', 'apple', 'pear', 'orange', 'banana']

2. 使用 list.sort() 方法,列表自身被排序

>>> basket.sort()
>>> basket
['apple', 'apple', 'banana', 'orange', 'orange', 'pear']

>>> basket.sort(key=lambda a: len(a), reverse=True)        # 通过key传入一个用于计算排序值的函数
>>> basket
['banana', 'orange', 'orange', 'apple', 'apple', 'pear']

字符串(str)与字节串(bytes、bytearray)

strbytesbytearray 有许多相似之处,但需要记住,str 是文本序列,而 bytesbytearray 是二进制序列,因此字节串对象中的元素其实是 0 到 255 的整数。strbytes不可变序列bytearray可变序列

  • 在 Python 中处理文本数据是使用 str 对象,也称为 字符串。 字符串是由 Unicode 码位 构成的不可变序列。之前提到过,字符串的字面值可以用 '"'''""" 表示。也提到过字符串变量和字符串字面值的区别。

  • 表示 bytes 字面值的语法与字符串字面值的大致相同,只是添加了一个 b 前缀。另外,bytes 字面值中只允许 ASCII 字符(无论源代码声明的编码为何)。 任何超出 127 的二进制值必须使用相应的转义序列形式加入 bytes 字面值。

>>> b'This is a ByteString.'
b'This is a ByteString.'
>>> b'中文'
  File "<stdin>", line 1
    b'中文'
         ^
SyntaxError: bytes can only contain ASCII literal characters.
>>> b'\xe4\xb8\xad\xe6\x96\x87'
b'\xe4\xb8\xad\xe6\x96\x87'

官方文档关于字符串与字节串字面值的详细说明看这里:https://docs.python.org/zh-cn/3/reference/lexical_analysis.html#strings

  • strbytes 都可以使用 r 前缀来禁用转义序列处理,例如:
>>> print('C:\some\name')  # here \n means newline!
C:\some
ame
>>> print(r'C:\some\name')  # note the r before the quote
C:\some\name

>>> print('\u4e2d\u6587')
中文
>>> print(r'\u4e2d\u6587')
\u4e2d\u6587

>>> len(b'a\nb')
3
>>> len(rb'a\nb')
4
  • bytearray 对象是 bytes 对象的可变对应物。因为字面值是常量值的表示法,所以 bytearray 没有专属的字面值语法,它们总是通过调用构造函数来创建。

字符串

str 的构造函数为:
class str(object=‘’)
class str(object=b’', encoding=‘utf-8’, errors=‘strict’)

当参数 encodingerrors 都没有时,调用的是第一个构造函数,返回 type(object).__str__(object),如果对象没有 __str__() 方法,则返回 repr(object) 的值。

>>> str(t)
"([0, 1], [7, 8, 9], ['hello'])"
>>> class A:
...     pass
...
>>> myclass = A()
>>> str(myclass)
'<__main__.A object at 0x000001C3E90009D0>'

>>> type(myclass).__str__(myclass)
'<__main__.A object at 0x000001C3E90009D0>'
>>> from math import ceil
>>> str(ceil)
'<built-in function ceil>'
>>> str(b'\xe4\xb8\xad\xe6\x96\x87')
"b'\\xe4\\xb8\\xad\\xe6\\x96\\x87'"

当参数 encodingerrors 至少传入一个时,调用的是第二个构造函数,此时 object 应该是一个 bytesbytearray 对象,等价于bytes.decode(encoding, errors)

>>> str(b'\xe4\xb8\xad\xe6\x96\x87', encoding='utf-8')
'中文'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'

字符串支持所有不可变序列的操作。同时还提供了许多额外的方法。这里对常见的字符串操作和方法做一些说明。

字符串拼接

(1) 字面值特有的拼接方式:

>>> s = ('This is a long long long' ' ... '
...      'sentense. ')
>>> s
'This is a long long long ... sentense. '

(2) 使用 + 进行拼接(适用于字符串变量和字面值):

>>> s1 = 'Hello!'
>>> s2 = 'World!'
>>> s3 = s1 + ' ' + s2
>>> s3
'Hello! World!'

(3) 使用 * 进行重复拼接(适用于字符串变量和字面值):

>>> s1 = 'hello~' * 5
>>> s1
'hello~hello~hello~hello~hello~'

(4) 使用 str.join() 进行拼接(适用于字符串变量和字面值):

>>> '--'.join('ABCD')
'A--B--C--D'
>>> '.'.join(['www','somesite','com'])
'www.somesite.com'
>>> ''.join(['aa','bb','cc','dd'])
'aabbccdd'
字符串索引与切片

字符串索引与切片,即字符序列索引与切片,与其他序列的索引与切片逻辑是一致的。

字符串支持 索引 (下标访问),第一个字符的索引是 0。索引还支持负数,用负数索引时,从右边开始计数。-0 和 0 一样,因此,负数索引从 -1 开始。

>>> s = 'Python世界'
>>> for i in range(len(s)):
...     print(str(i) + ':' + s[i])
...
0:P
1:y
2:t
3:h
4:o
5:n
6:7:
>>> for i in reversed(range(- len(s), 0)):
...     print(str(i) + ':' + s[i])
...
-1:-2:-3:n
-4:o
-5:h
-6:t
-7:y
-8:P

索引可以提取单个字符,切片 则提取子字符串:

>>> print(s[3:7])
hon世
>>> print(s[-6:-2])
thon

省略开始索引时,默认值为 0;省略结束索引时,默认为到字符串的结尾。
注意,输出结果包含切片开始,但不包含切片结束。因此,s[:i] + s[i:] 总是等于 s

还可以这样理解切片,索引指向的是字符 之间 ,第一个字符的左侧标为 0,最后一个字符的右侧标为 n ,n 是字符串长度。例如:

 +---+---+---+---+---+---+----+----+
 | P | y | t | h | o | n | 世 | 界 |
 +---+---+---+---+---+---+----+----+
 0   1   2   3   4   5   6    7    8
-8  -7  -6  -5  -4  -3  -2   -1

对于使用非负索引的切片,如果两个索引都不越界,切片长度就是起止索引之差。例如, s[3:7] 的长度是 4。

索引越界会报错

>>> s[40]  # the string only has 8 characters
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range

但是,切片会自动处理越界索引

>>> s[4:40]
'on世界'
>>> s[40:]
''
字符串查找

str.count(sub[, start[, end]])
返回子字符串 sub 在 [start, end] 范围内非重叠出现的次数。 可选参数 startend 会被解读为切片表示法。

>>> s = 'Type "help", "copyright", "credits" or "license" for more information.'
>>> s.count('or')
4

str.find(sub[, start[, end]])
返回子字符串 sub 在 s[start : end] 切片内被找到的最小索引。 可选参数 startend 会被解读为切片表示法。 如果 sub 未被找到则返回 -1。

str.index(sub[, start[, end]])
类似于 find(),但在找不到子字符串时会引发 ValueError

类似的还有 str.rfind(sub[, start[, end]])str.rindex(sub[, start[, end]])

>>> s = 'Type "help", "copyright", "credits" or "license" for more information.'
>>> s.find('or')
36
>>> s.rfind('or')
61

使用正则表达式

>>> import re
>>> s = 'Type "help", "copyright", "credits" or "license" for more information.'
>>> re.search('\\"[a-z]+\\"', s)
<re.Match object; span=(5, 11), match='"help"'>

>>> re.match('[a-z]+', s, re.IGNORECASE)
<re.Match object; span=(0, 4), match='Type'>

>>> m = re.fullmatch(r'(\"?[a-z]+\"?,?( |\.))+', s, re.IGNORECASE)
>>> if m:
...   print(m.group())
...
Type "help", "copyright", "credits" or "license" for more information.

>>> re.findall(r'\"\w*\"', s)
['"help"', '"copyright"', '"credits"', '"license"']
字符串拆分

str.partition(sep)
sep 首次出现的位置拆分字符串,返回一个 3 元组,其中包含分隔符之前的部分、分隔符本身,以及分隔符之后的部分。 如果分隔符未找到,则返回的 3 元组中包含字符本身以及两个空字符串。

类似的还有 str.rpartition(sep)

>>> s.partition('or')
('Type "help", "copyright", "credits" ', 'or', ' "license" for more information.')
>>> s.rpartition('or')
('Type "help", "copyright", "credits" or "license" for more inf', 'or', 'mation.')

str.split(sep=None, maxsplit=-1)
返回一个由字符串内单词组成的列表,使用 sep 作为分隔字符串。 如果给出了 maxsplit,则最多进行 maxsplit 次拆分。如果 sep 未指定或为 None,则连续的空格会被视为单个分隔符。

类似的还有 str.rsplit(sep=None, maxsplit=-1)

>>> s.split('or')
['Type "help", "copyright", "credits" ', ' "license" f', ' m', 'e inf', 'mation.']
>>> s.rsplit(maxsplit=2)
['Type "help", "copyright", "credits" or "license" for', 'more', 'information.']

使用正则表达式拆分字符串:

>>> import re
>>> s = 'Type "help", "copyright", "credits" or "license" for more information.'
>>> re.split(r'\"?,? \"?', s)
['Type', 'help', 'copyright', 'credits', 'or', 'license', 'for', 'more', 'information.']
字符串格式化

(1) printf 风格的字符串格式化

字符串具有一种特殊的内置操作:使用 % (取模) 运算符。 这也被称为字符串的 格式化 或 插值 运算符。 对于 format % values (其中 format 为一个字符串),在 format 中的 % 转换标记符将被替换为零个或多个 values 条目。 其效果类似于在 C 语言中使用 sprintf()

>>> print('Hello %s.' % 'python')
Hello python.

>>> print('%d-%02d-%02d' % (2022, 5, 2))
2022-05-02

>>> print('Value: %010.4f%%' % 20.13)
Value: 00020.1300%

>>> import decimal
>>> v = decimal.Decimal('12.34567')
>>> print('Value: %10.4f%%' % v)
Value:    12.3457%

>>> print('ASCII: %#x' % b'A'[0])
ASCII: 0x41

>>> print('%(language)s has %(number)03d quote types.' %
...       {'language': "Python", "number": 2})
Python has 002 quote types.

(2) str.format() 方法
str.format(*args, **kwargs)
执行字符串格式化操作。 调用此方法的字符串可以包含字符串字面值或者以花括号 {} 括起来的替换域。 每个替换域可以包含一个位置参数的数字索引,或者一个关键字参数的名称。 返回的字符串副本中每个替换域都会被替换为对应参数的字符串值。

>>> print("Hello {}".format('python'))
Hello python

>>> print('{}-{:02d}-{:02d}'.format(2022, 5, 2))
2022-05-02

>>> print('Value: {:010.4f}%'.format(20.13))
Value: 00020.1300%

>>> print('Value: {{{:10.4f}%}}'.format(20.13))
Value: {   20.1300%}

>>> import decimal
>>> v = decimal.Decimal('12.34567')
>>> print('Value: {:10.4f}%'.format(v))
Value:    12.3457%

>>> print('ASCII: {:#x}'.format(b'A'[0]))
ASCII: 0x41

>>> print('Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W'))
Coordinates: 37.24N, -115.81W

>>> coord = {'latitude': '37.24N', 'longitude': '-115.81W'}
>>> print('Coordinates: {latitude}, {longitude}'.format(**coord))
Coordinates: 37.24N, -115.81W

(3) 格式字符串字面值

格式字符串字面值 或称 f-string 是标注了 ‘f’ 或 ‘F’ 前缀的字符串字面值。这种字符串可包含替换字段,即以 {} 标注的表达式。其他字符串字面值只是常量,格式字符串字面值则是可在运行时求值的表达式。

>>> lang = 'python'
>>> print(f'Hello {lang!s}.')
Hello python.

>>> year = 2022
>>> month = 5
>>> day = 2
>>> print(f'{year}-{month:02d}-{day:02d}')
2022-05-02

>>> d = {'year':2022, 'month':5, 'day':2}
>>> print(f'{d["year"]}-{d["month"]:02d}-{d["day"]:02d}')
2022-05-02

>>> width = 10
>>> precision = 6
>>> value = decimal.Decimal("12.34567")
>>> print(f'Value: {value:{width}.{precision}}')
Value:    12.3457

>>> print(f'Value: {value:10.4f}') # 4代表小数位数
Value:    12.3457
>>> print(f'Value: {value:10.4}')  # 4代表精度
Value:      12.35

>>> print(f'ASCII: {b"A"[0]:#x}')
ASCII: 0x41
字符串转换为字节串

str.encode(encoding='utf-8', errors='strict')
返回原字符串编码为 bytes 对象的版本。 默认编码为 ‘utf-8’。 可以给出 errors 来设置不同的错误处理方案。 errors 的默认值为 ‘strict’,表示编码错误会引发 UnicodeError

>>> s = 'Python世界'
>>> s.encode('utf-8')
b'Python\xe4\xb8\x96\xe7\x95\x8c'
其他字符串方法

详细文档参考:https://docs.python.org/zh-cn/3/library/stdtypes.html#string-methods

  • 大小写转换:str.capitalize() / str.lower() / str.upper() / str.swapcase() / str.casefold()
  • 判断字符串类型:str.isalnum() / str.isalpha() / str.isdecimal() / str.isdigit() / str.isnumeric() / str.isascii() / str.isprintable() / str.isspace()
  • 字符串填充:str.ljust(width[, fillchar]) / str.rjust(width[, fillchar]) / str.center(width[, fillchar])
  • 移除字符: str.lstrip([chars]) / str.rstrip([chars]) / str.strip([chars])
  • 前缀后缀:str.startswith(prefix[, start[, end]]) / str.endswith(suffix[, start[, end]]) / str.removeprefix(prefix, /) / str.removesuffix(suffix, /)
  • 左填充’0’:str.zfill(width)
  • 字符串替换:str.replace(old, new[, count])

str.lstrip()str.removeprefix() 的区别:

>>> 'Hello python.'.lstrip('Helo')
' python.'
>>> 'Hello python.'.removeprefix('Hello')
' python.'

>>> 'Arthur: three!'.lstrip('Arthur: ')
'ee!'
>>> 'Arthur: three!'.removeprefix('Arthur: ')
'three!'

str.isnumeric() str.isdigit()str.isdecimal() 的区别:

>>> '52'.isnumeric()
True
>>> '52'.isdigit()
True
>>> '52'.isdecimal()
True

>>> '52'.isnumeric()
True
>>> '52'.isdigit()
True
>>> '52'.isdecimal()
True

>>> '⒌⒉'.isnumeric()
True
>>> '⒌⒉'.isdigit()
True
>>> '⒌⒉'.isdecimal()
False

>>> '⑸⑵'.isnumeric()
True
>>> '⑸⑵'.isdigit()
True
>>> '⑸⑵'.isdecimal()
False

>>> '五十二'.isnumeric()
True
>>> '五十二'.isdigit()
False
>>> '五十二'.isdecimal()
False

>>> '㈤㈡'.isnumeric()
True
>>> '㈤㈡'.isdigit()
False
>>> '㈤㈡'.isdecimal()
False

>>> 'ⅩⅩⅩⅩⅩⅡ'.isnumeric()
True
>>> 'ⅩⅩⅩⅩⅩⅡ'.isdigit()
False
>>> 'ⅩⅩⅩⅩⅩⅡ'.isdecimal()
False

字节串

前面提到,bytes 字面值的语法与字符串字面值的大致相同,只是添加了一个 b 前缀。

除了字面值形式,bytes 对象还可以通过其他几种方式来创建:

  • 指定长度的以零值填充的 bytes 对象: bytes(10)
  • 通过由整数组成的可迭代对象: bytes(range(20))
  • 通过缓冲区协议复制现有的二进制数据: bytes(obj)

bytearray 对象可以通过以下方式创建:

  • 创建一个空实例: bytearray()
  • 创建一个指定长度的以零值填充的实例: bytearray(10)
  • 通过由整数组成的可迭代对象: bytearray(range(20))
  • 通过缓冲区协议复制现有的二进制数据: bytearray(b'Hi!')

十六进制数形式的字符串与 bytesbytearray 对象相互转换:

classmethod fromhex(string)hex([sep[, bytes_per_sep]])

>>> bytes.fromhex('41F0 f1f2')
b'A\xf0\xf1\xf2'
>>> b'A\xf0\xf1\xf2'.hex()
'41f0f1f2'

>>> bytearray.fromhex('41F0 f1f2')
bytearray(b'A\xf0\xf1\xf2')
>>> bytearray(b'\x41\xf0\xf1\xf2').hex('-',2)
'41f0-f1f2'

由于 bytes 对象是由整数构成的序列(类似于元组),因此对于一个 bytes 对象 bb[0] 将为一个整数,而 b[0:1] 将为一个长度为 1 的 bytes 对象。 (这与文本字符串不同,索引和切片所产生的将都是一个长度为 1 的字符串)。

总是可以使用 list(b)bytesbytearray 对象转换为一个由整数构成的列表。

>>> b = bytes.fromhex('41F0 f1f2')
>>> list(b)
[65, 240, 241, 242]

>>> list(bytearray(b'\x41\xf0\xf1\xf2'))
[65, 240, 241, 242]

bytesbytearray 支持所有通用的序列操作bytearray 还支持可变序列的操作。另外,bytesbytearray 还支持很多与 str 中的方法类似的方法,例如 endswith()find()strip() 等等。具体可参考:bytes 和 bytearray 操作bytesbytearray 也都支持 printf风格的格式化

前面提到,可以用 str.encode() 方法将字符串转换为 bytes 对象。相反的,可以用 decode() 方法将 bytesbytearray 对象转换为字符串。
bytes.decode(encoding='utf-8', errors='strict')
bytearray.decode(encoding='utf-8', errors='strict')
返回从给定 bytes 解码出来的字符串。 默认编码为 ‘utf-8’。 可以给出 errors 来设置不同的错误处理方案。

>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode()
'中文'
>>> bytearray([0xe4,0xb8,0xad,0xe6,0x96,0x87]).decode()
'中文'

集合(frozenset、set)

frozensetset 是一对性质相似的类型。区别在于 frozenset不可变类型,而 set可变类型

集合是由不重复元素组成的无序容器。基本用法包括成员检测、消除重复元素。集合对象支持合集、交集、差集、对称差分等数学运算。

与其他多项集一样,集合也支持 x in set, len(set)for x in set。 作为一种无序的多项集,集合并不记录元素位置或插入顺序。 相应地,集合不支持索引、切片或其他序列类的操作。

集合可用多种方式来创建:

  • 使用花括号内以逗号分隔元素的方式: {'jack', 'sjoerd'}
  • 使用集合推导式: {c for c in 'abracadabra' if c not in 'abc'}
  • 使用类型构造器: set(), set('foobar'), set(['a', 'b', 'foo'])

注意,创建空集合只能用 set(),不能用 {},{} 创建的是空字典

>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # unique letters in a
{'a', 'r', 'b', 'c', 'd'}
>>> a - b                              # letters in a but not in b
{'r', 'd', 'b'}
>>> a | b                              # letters in a or b or both
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b                              # letters in both a and b
{'a', 'c'}
>>> a ^ b                              # letters in a or b but not both
{'r', 'd', 'b', 'm', 'z', 'l'}

frozensetset 的方法详见:https://docs.python.org/zh-cn/3/library/stdtypes.html#set-types-set-frozenset


字典(dict)

Mapping 对象会将 hashable 值映射到任意对象。 映射属于可变对象。 目前仅有一种标准映射类型 dict

  • 字典以 关键字 为索引,关键字通常是字符串或数字,也可以是其他任意不可变类型
  • 可以把字典理解为 键值对 的集合,但字典的键必须是唯一的
  • 字典的主要用途是通过关键字存储、提取值。用 del 语句可以删除键值对。用已存在的关键字存储值,与该关键字关联的旧值会被取代。通过不存在的键提取值,则会报错。
  • 对字典执行 list(d) 操作,返回该字典中所有键的列表,按插入次序排列(如需排序,请使用 sorted(d))。
  • 检查字典里是否存在某个键,使用关键字 in
  • dict.keys(), dict.values()dict.items() 所返回的对象是 视图对象。 该对象提供字典条目的一个动态视图,这意味着当字典改变时,视图也会相应改变。

以下示例返回的字典均等于 {"one": 1, "two": 2, "three": 3}:

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> f = dict({'one': 1, 'three': 3}, two=2)
>>> a == b == c == d == e == f
True

在字典中循环时,用 items() 方法可同时取出键和对应的值:

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
...     print(k, v)
...
gallahad the pure
robin the brave

dict 的方法详见:https://docs.python.org/zh-cn/3/library/stdtypes.html#mapping-types-dict


数据结构

建议读一读官方文档这一章节:https://docs.python.org/zh-cn/3/tutorial/datastructures.html


枚举(Enum)

完整文档参考:对枚举的支持

>>> from enum import Enum
>>> class Color(Enum):
...     RED = 1
...     GREEN = 2
...     BLUE = 3
...
>>> print(Color.RED)
Color.RED

成员值可以是 intstr 等。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《A Byte of Python3》是一本面向初学者的Python编程入门书籍,也是学习Python3的良好选择。这本书的作者是Swaroop C H,他深入浅出地介绍了Python3的基本概念和语法,使得初学者能够顺利入门并掌握Python编程的基本技能。 这本书的中文完整版被称为《A Byte of Python3》中文翻译版,由IT学院翻译小组翻译并发布。中文翻译版的内容与英文原版一样具有完整性,其目的是为了方便那些不懂英文的读者能够更好地学习和掌握Python3编程语言。 这本书的特点是讲解思路清晰,语言简洁明了,知识点由浅入深,适合初学者阅读。它从Python的安装开始介绍,然后涵盖了Python的基本语法、数据类型、函数、条件语句、循环语句、列表、字典、元组、文件操作等内容。每个章节都以实例的形式进行讲解,并配有相关的练习题,方便读者巩固所学知识。 此外,这本书还包括了一些高级主题,如类和对象、模块和包、异常处理等内容,有助于读者进一步提升Python编程技能。同时,书中还介绍了Python的标准库和一些常用的第三方库,以及如何使用Python进行Web开发和数据库操作等。 总的来说,《A Byte of Python3》中文完整版是一本非常实用的Python编程入门书籍,适合初学者阅读和学习。通过阅读这本书,读者可以轻松掌握Python3的基本语法和编程技能,为进一步深入学习和实践打下坚实的基础。 ### 回答2: 《A Byte of Python3》是一本关于Python编程语言的完整教程。这本书的目的是介绍Python的基本知识和编程概念,以帮助读者快速入门并掌握Python的基本语法和用法。 这本书内容编排合理,结构清晰,以简洁易懂的方式介绍了Python的基础知识,包括变量、运算符、表达式、条件语句、循环语句等。同时,它还介绍了Python的函数和模块,如何创建自定义函数和使用内置函数,以及如何利用模块进行代码复用。 除了基本语法和概念,这本书还介绍了Python的文件操作、异常处理、面向对象编程等高级话题,使读者能够更深入地理解Python的强大功能和灵活性。 这本书的优点是讲解深入浅出,循序渐进。它使用大量的示例和练习,帮助读者巩固所学的知识,并提供了一些实际的项目和案例,让读者能够将所学的知识应用到实际中去。 总的来说,《A Byte of Python3》是一本非常适合初学者的Python教程。它没有过多的理论概念,而是注重实践和应用。通过阅读这本书,读者可以快速入门并掌握Python编程的基本技能,为进一步学习和应用Python打下良好的基础。 ### 回答3: 《A Byte of Python3(中文完整版)》是一本介绍Python编程语言的书籍。该书适用于初学者,通过简洁明了的说明和示例,帮助读者了解Python的基础知识和编程技巧。 书中首先介绍了Python的基本概念和特点,如变量、数据类型、运算符等。接着详细讲解了控制流程和函数的使用,包括条件语句、循环语句和函数的定义与调用。读者可以通过这些知识建立起对Python编程的基础理解。 随后,作者进一步介绍了Python的模块和包的使用,包括标准库中常用的模块以及如何使用第三方模块。读者可以学习到如何调用现有的模块,以及如何自己创建和使用模块。 书中还对面向对象编程进行了深入讲解,包括类的定义与继承、封装和多态等概念。通过这些内容,读者可以学会如何使用Python进行面向对象的编程,并掌握一些高级的编程技巧。 此外,《A Byte of Python3(中文完整版)》还介绍了Python的文件处理、异常处理、正则表达式和网络编程等知识。这些内容为读者提供了更广阔的应用领域和深度学习的机会。 总的来说,这本书适合编程初学者入门Python编程。它以简洁明了的方式介绍了Python的基础知识和编程技巧,帮助读者建立起对Python编程的基础理解,并提供了更深入的学习和应用方向。无论是作为入门教材还是作为参考书,这本《A Byte of Python3(中文完整版)》都是学习Python的不错选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值