Python的数字类型

Python 数字类型的完整工具包括:

  • 整数和浮点数
  • 复数
  • 固定精度的十进制数
  • 有理分数
  • 集合
  • 布尔类型
  • 无穷的整数精度
  • 各种数字内置函数和模块

1.1 数字常量(Literals)

基本数字常量

常量 解释
1234, -24, 0, 99999999 整数(无穷大小)
1.23, 1., 3.14e-10, 4E210, 4.0e+210 浮点数
0o177, 0x9ff, 0b101010 八进制、十六进制和二进制常量
3+4j, 3.0+4.0j, 3j 复数常量
set(‘spam’), {1, 2, 3, 4} 集合
Decimal(‘1.0’), Fraction(1, 3) 小数和分数扩展类型
bool(X), True, False 布尔类型和常数

1.2 Python 表达式操作符

Python 表达式操作符和程序

操作符 描述
yield x 生成器函数发送协议
lambda args: expression 生成匿名函数
x if y else z 三元选择表达式
x or y 逻辑或(只有 x 为假,才会计算 y)
x and y 逻辑与(只有 x 为真,才会计算 y)
not x 逻辑非
x in y, x not in y 成员关系(可迭代对象、集合)
x is y, x is not y 对象实体测试
x < y, x <= y, x > y, x >= y 大小比较,集合子集和超集
x == y, x != y 值相等性操作符
x y 位或,集合并集
x ^ y 位异或,集合对称差
x & y 位与,集合交集
x << y, x >> y 左移或右移 y 位
x + y 加法,合并
x - y 减法,集合差集
x * y 乘法,重复
x % y 余数,格式化
x / y, x // y 除法:真除法或 floor 除法
-x, +x 一元减法,识别
~x 按位求补(取反)
x ** y 幂运算
x[i] 索引(序列、映射及其他)
x[i:j:k] 分片
x(…) 调用(函数、方法、类及其他可调用的)
x.attr 属性引用
(…) 元组,表达式,生成器表达式
[…] 列表,列表解析
{…} 字典、集合、集合和字典解析

上表中操作符越靠后的优先级越高。

在混合类型的表达式中,Python 首先将被操作的对象转换成其中最复杂的操作对象的类型,然后再对相同类型的操作对象进行数学运算。整数比浮点数简单,浮点数比复数简单。

  1. 在实际应用中的数字

2.1 变量和基本的表达式

在Python中:

  • 变量在它第一次赋值时创建。
  • 变量在表达式中使用将被替换为它们的值。
  • 变量在表达式中使用以前必须已赋值。
  • 变量像对象一样不需要在一开始进行声明。

在 Python 中,变量并不需要预先声明,但是在使用之前,至少要赋一次值。

1
2
a = 3             # 赋值会让变量 a 和 b 自动生成
b = 4
1
a + 1, b * 3
(4, 12)

2.2 比较:一般的和连续的

1
1 < 2 
True
1
2.0 >= 1     # 大于等于:混合类型 1 转换为 1.0
True
1
2.0 == 2.0
True
1
2.0 != 2.0
False

Python 允许我们把多个比较连续起来执行范围测试:

1
2
3
4
X = 2              
Y = 4
Z = 6
X < Y < Z # 连续比较,相当于 X < Y and Y < Z
True
1
X < Y > Z           # 相当于 X < Y and Y > Z
False

2.3 除法:Floor 除法和真除法

X / Y
真除法,无论任何类型都会保持小数部分。
X // Y\

Floor 除法,不考虑操作对象的类型,运算结果总是向负无穷的方向舍入。

1
10 / 4
2.5
1
10 // 4
2
1
10 // 4.0
2.0
1
5 // -2      # 向下舍入
-3

2.4 复数

1
1j * 1J
(-1+0j)
1
2 + 1j * 3
(2+3j)
1
(2 + 1j) * 3
(6+3j)
1
complex('1+2j')  # 将字符串或数字转换成复数,字符串 + - 周围不能有空格
(1+2j)
1
complex(1)
(1+0j)

2.5 十六进制、八进制、二进制:常量和转换

这些常量只是指定一个整数对象的值的一种替代方法。

1
0o1, 0o20, 0o377          # 八进制常量,数字 0-7
(1, 16, 255)
1
0x01, 0x10, 0xFF          # 十六进制常量,数字 0-9/A-F
(1, 16, 255)
1
0b1, 0b10000, 0b11111111  # 二进制常量,数字 0-1
(1, 16, 255)

Python 默认使用十进制值显示,但它提供了内置的函数,允许把整数转换为其他进制的数字字符串:

1
oct(64), hex(64), bin(64)      # 八进制,十六进制,二进制
('0o100', '0x40', '0b1000000')

内置的 int 函数可以将一个数字字符串转换为整数,并可以通过定义的第二个参数来指定数字的进制:

1
64, 0o100, 0x40, 0b1000000
(64, 64, 64, 64)
1
int('64'), int('100', 8), int('40', 16), int('1000000', 2)
(64, 64, 64, 64)
1
int('0x40', 16), int('0b1000000', 2)
(64, 64)

可以使用字符串格式化方法调用和表达式将一个整数转换为八进制数和十六进制数的字符串:

1
'{0:o}, {1:x}, {2:b}'.format(64, 64, 64)
'100, 40, 1000000'

2.6 位操作

1
2
x = 1                # 0001
x << 2 # 左移两位:0100
4
1
x | 2                # 位或:0011
3
1
x & 1                # 位与:0001
1
1
2
X = 0b0001           # 二进制常量
bin(X << 2) # 二进制数字符串
'0b100'
1
bin(X | 0b010)
'0b11'
1
bin(X & 0b1)
'0b1'
1
2
X = 0xFF              # 十六进制数
bin(X ^ 0b10101010)
'0b1010101'

2.7 其他的内置数学工具

1
2
import math
math.pi, math.e # 通用常数
(3.141592653589793, 2.718281828459045)
1
math.sin(2 * math.pi / 180)         # sin, tan, cos
0.03489949670250097
1
math.sqrt(144)                      # 平方根
12.0
1
pow(2, 4), 2 ** 4                   # 指数(幂)
(16, 16)
1
abs(-42.0), sum((1, 2, 3, 4))       # 绝对值,加和
(42.0, 10)
1
min(3, 1, 2, 4), max(3, 1, 2, 4)    # 最小值,最大值
(1, 4)
1
math.floor(2.567), math.floor(-2.567)    # 向下取整
(2, -3)
1
math.trunc(2.567), math.trunc(-2.567)    # 截断(去掉小数部分)
(2, -2)
1
round(2.567), round(2.467), round(2.567, 2)
(3, 2, 2.57)
  1. 其他数字类型

3.1 小数数字

小数通过一个导入的模块调用函数后创建,而不是通过运行常量表达式创建。小数对象有固定的位数和小数点,因此有固定的精度。

浮点数学缺乏精确性,因为用来存储数值的空间有限。例如,下面的计算应该得到零,但是结果却没有。结果接近零,但却没有足够的位数去实现这样的精度

1
0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17

使用小数对象,结果能够改正,参数可以是整数,字符串,元组,float,或另一个 Decimal 对象。

1
2
from decimal import Decimal
Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

当不同精度的小数在表达式中混编时,Python 自动升级为小数位数最多的

1
2
from decimal import Decimal
Decimal('0.1') + Decimal('0.10')
Decimal('0.20')

Python 也允许直接使用浮点数,转换是精确的,但有时会产生大量的默认数字,除非它们被固定位数。

1
2
from decimal import Decimal
Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3)
Decimal('2.775557561565156540423631668E-17')

设置全局精度

1
2
3
import decimal
decimal.getcontext().prec = 4
decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1429')

小数上下文管理器
可以使用上下文管理器语句来重新设置临时精度。在语句退出后,精度又重新设置为初始值:

1
2
3
4
import decimal
with decimal.localcontext() as ctx:
ctx.prec = 2
decimal.Decimal('1.00') / decimal.Decimal('3.00')

3.2 分数类型

分数类型实现了一个有理数对象,明确保留了一个分子和一个分母,从而避免了浮点数学的某些不精确性和局限性

1
2
3
from fractions import Fraction
x = Fraction(1, 3) # 分子,分母
x
Fraction(1, 3)
1
print(x)
1/3
1
x + x
Fraction(2, 3)
1
Fraction('.25')                 # 也可以使用浮点数字符串来创建
Fraction(1, 4)

转换和混合类型

1
(2.5).as_integer_ratio()        # 浮点对象方法
(5, 2)
1
2
x = Fraction(*2.5.as_integer_ratio())     # 浮点转换为分数,和 Fraction(5, 2) 相同
x
Fraction(5, 2)
1
float(x)                                  # 分数转换为浮点数
2.5
1
Fraction.from_float(1.75)                 # 浮点数转换为分数,另一种方法
Fraction(7, 4)

3.3 集合(Set)

集合是一些唯一的、不可变的对象的一个无序集合,这些对象支持与数学集合理论相对应的操作。

要创建一个集合对象,需要向内置的 set 函数传递一个序列或其他的可迭代的对象。

1
2
3
4
x = set('abcde')
# Python 3 允许使用花括号创建集合:{1, 2, 3, 4}
y = set('bdxyz')
x
{'b', 'd', 'x', 'y', 'z'}

集合通过表达式操作符支持一般的数学集合运算。

不能在一般序列上应用这些表达式,必须通过序列创建集合后才能使用。

1
'e' in x            # 成员关系 
True
1
x - y               # 差集
{'a', 'c', 'e'}
1
x | y               # 并集
{'a', 'b', 'c', 'd', 'e', 'x', 'y', 'z'}
1
x & y               # 交集,x.intersection(y)
{'b', 'd'}
1
x ^ y               # 对称差(XOR)
{'a', 'c', 'e', 'x', 'y', 'z'}
1
x > y, x < y        # 超子集,子集
(False, False)
1
2
3
# 方法
z = x.intersection(y)
z
{'b', 'd'}
1
2
z.add('SPAM')        # 插入一项
z
{'SPAM', 'b', 'd'}
1
2
z.update(set(['X', 'Y']))       # 融合:原处并集操作
z
{'SPAM', 'X', 'Y', 'b', 'd'}
1
2
z.remove('b')                   # 删除一项
z
{'SPAM', 'X', 'Y', 'd'}

集合也可用于 len、for 循环和列表解析,但由于集合是无序的,所以不支持索引和分片这样的操作。

1
2
for item in set('abc'):
print(item * 3)
bbb
ccc
aaa

空的集合必须通过内置函数set()创建。

集合只能包含不可变的对象类型,因此,列表和字典不能嵌入到集合中,但是元组可以。

1
2
S = {1.23}
S.add([1, 2, 3])
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-34-40944404bb92> in <module>()
      1 S = {1.23}
----> 2 S.add([1, 2, 3])


TypeError: unhashable type: 'list'
1
S.add({'a': 1})
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-35-d6f809fee825> in <module>()
----> 1 S.add({'a': 1})


TypeError: unhashable type: 'dict'
1
2
S.add((1, 2, 3))
S
{(1, 2, 3), 1.23}

集合解析(set comprehension)
集合解析运行一个循环并在每次迭代时收集一个表达式的结果,通过一个循环变量来访问当前的迭代值以用于集合表达式中。

1
{x ** 2 for x in [1,2,3,4]}    # 对于列表中的每一个 x,给出包含 x 的平方的一个新的集合
{1, 4, 9, 16}
1
{x * 4 for x in 'spam'}
{'aaaa', 'mmmm', 'pppp', 'ssss'}

3.4 布尔型

bool,其值为 True 和 False,其值是预先定义的内置的变量名。在内部,新的变量名 True 和 False 是 bool 的实例,实际上仅仅是内置的整数类型 int 的子类。

True 和 False 的行为和整数 1 和 0 是一样的,除了它们有特定的显示逻辑。

1
type(True)
bool
1
isinstance(True, int)
True
1
True == 1               # 值相等
True
1
True is 1               # 但是是不同对象
False
1
True + 4
5