2.Python数值类型
2.1 数值类型基础知识
在Python 中,数字并不真的只是一种对象类型,而是一组相似类型的分类。
Python 数值类型工具包括:
• 整数和浮点对象
• 复数对象
• 小数:固定精度对象
• 分数:有理数对象
• 集合:带有数值运算的集合体
• 布尔值:真和假
• 内置函数和模块: round 、math 、random 等
• 表达式: 无限制整数精度;位运算;十六进制、八进制和二进制格式
• 第三方扩展:向量、库、可视化、作图等
2.1.1 数值字面量
Python数值字面量和构造函数:
常量 | 解释 |
---|---|
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'), | 集合 |
Decimal('1.0'), Fraction(1, 3) | 小数和分数扩展类型 |
bool(X), True, False | 布尔类型和常数 |
浮点型字面量
浮点数带一个小数点,python浮点数可以带上科学计数法标志e或者E。如果数字带有小数点,哪怕小数点后面没有数字(如1.
),python也是创建浮点数对象。浮点数在Python中采用“双精度”。
八进制/十六进制/二进制字面量
十六进制字面量以0x或0X开头,后面接着十六进制的数字0-9和A-F;
八进制字面量以0o或oO开头,后面接着八进制数字0-7;
二进制字面量以0b或0B开头,后面接着二进制数字0-1;
复数字面量
复数字面量是以实部+虚部组成,其中虚部以j或J结尾,实部可以忽略,复数可以通过 complex(real, imag) 来创建。
2.1.2 Python表达式运算符
操作符 | 描述 |
---|---|
yield x | 生成器函数发送协议 |
lambda args: expression | 生成匿名函数 |
x if y else z | 三元选择表达式(当y为真时,才会计算x) |
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 | 除法:真除法(x / y)或 floor 除法(x // y,即向下取整) |
-x, +x | 一元减法,识别 |
~x | 按位求补(取反) |
x ** y | 幂运算 |
x[i] | 索引(序列、映射及其他) |
x[i:j:k] | 分片 |
x(...) | 调用(函数、方法、类及其他可调用的) |
x.attr | 属性引用 |
(...) | 元组,表达式,生成器表达式 |
[...] | 列表,列表解析 |
字典、集合、集合和字典解析 |
上表中自上而下运算优先级递增。
混合运算遵循运算级优先级
在Python中混合运算将遵循运算符优先级,圆括号可以将表达式进行分组,表达式将优先执行圆括号中的运算,推荐将复杂的表达式使用圆括号增加可读性。
混合类型向上转换
在混合类型的表达式中, Python 首先将被操作数值类型的对象转换成其中最复杂的操作数的类型,然后再对相同类型的操作数进行数学运算。 Python 是这样划分数值类型的复杂度的:整数比浮点数简单,浮点数比复数简单。因此,将一个整数与一个浮点数进行混合运算时,整数将会被向上转换成浮点数,之后再与浮点数进行运算。
混合类型转换仅适用于数值类型的混合,而不能用于其他类型之间转换。如一个字符串和一个整数相加会产生错误。同时非数值混合类型之间也不允许比较。
2.1.3 数字的实际运用
变量与基础表达式
在Python 中:
• 变量在第一次赋值时被创建。
• 变量在表达式中使用时,会被替换成它们的值。
• 变量在表达式中使用之前,必须已被赋值。
• 变量引用对象,而且从不需要事先声明。
使用一个未被赋值的变量将会出现“未定义”错误。
>>> a = 3
>>> b = 4 # 赋值将自动创建变量a和变量b
>>> c # 使用未赋值的变量将出现未定义错误
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
c
NameError: name 'c' is not defined
普通比较与链式比较
普通比较:
>>> 1 < 2
True
>>> 2.0 >= 1.0
True
>>> 2.0 == 2.0
True
>>> 2.0 != 2.0
False
python还允许把多个比较链接起来执行范围测试:
>>> X = 2
>>> Y = 4
>>> Z = 6
>>> X < Y < Z # 相当于 X < Y and Y < Z
True
>>> X < Y > Z # 相当于 X < Y and Y > Z
False
>>> 1 == 2 < 3 # 相当于 1== 2 and 2 < 3,而并不是把 1==2的结果False与3进行小于比较
False
除法:经典除法、向下取整除法和真除法
在Python 3 . X 中,/
现在总是执行真除法,不管操作数的类型,都返回包含任何小数部分的一个浮点数结果。//
执行向下取整除法,它截除掉余数并针对整数操作数返回一个整数,如果有任何一个操作数是浮点数类型,则返回一个浮点数。
>>> 5 / 2 , 5 / -2
(2.5, -2.5)
>>> 5 // 2 , 5 // -2 # // 是向下取整,即小于商的最大整数
(2, -3)
>>> 5 / 2.0 , 5 / -2.0
(2.5, -2.5)
>>> 5 // 2.0, 5 // -2.0
(2.0, -3.0)
复数
>>> 1j * 1J
(-1+0j)
>>> 2 + 1j * 3
(2+3j)
>>> (2 + 1j) * 3
(6+3j)
十六进制、八进制和二进制:字面量和转换
字面量:
>>> 0o1, 0o20, 0o377
(1, 16, 255)
>>> 0x01, 0x10, 0xFF
(1, 16, 255)
>>> 0b1, 0b10000, 0b11111111
(1, 16, 255)
python提供了内置函数将十进制数字转换为十六进制、八进制和二进制数字:
oct
函数会将十进制数转换为八进制数字的字符串;hex
函数会将十进制转换为十六进制数字的字符串;bin
函数会将十进制数转换为二进制数字的字符串;
>>> oct(64), hex(64), bin(64)
('0o100', '0x40', '0b1000000')
内置函数int
会将一个数字的字符串转换为一个整数,并能通过可选的第二位参数来确定转换后数字的进制。
>>> 64, 0o100, 0x40, 0b1000000
(64, 64, 64, 64)
>>> int('64'), int('100', 8), int('40', 16), int('1000000', 2)
(64, 64, 64, 64)
>>> int('0o100', 8), int('0x40', 16), int('0b1000000', 2)
eval函数可以将字符串当作python代码来执行,因此也可以把进制数字字符串转换为整数:
>>> eval('64'), eval('0O100'), eval('0x40'), eval('0b1000000')
(64, 64, 64, 64)
也可以使用字符串格式化将整数转换为指定进制的字符串:
>>> '{0:o}, {1:x}, {2:b}'.format(64, 64, 64)
'100, 40, 1000000'
按位运算
>>> x = 1 # x = 0b0001
>>> x << 2 # 0b0001 << 2 = 0b0100
4
>>> x >> 2 # 0b0001 >> 2 = 0b0000
0
>>> x | 2 # 0b0001 | 0b0010 = 0b0011
3
>>> x & 1 # 0b0001 & 0b0001 = 0b0001
1
>>> x ^ 3 # 0b0001 ^ 0b0011 = 0b0010
2
Python 3.1 和2.7 引入了一个新的整数方法bit_length
, 它允许我们查询以二进制表示一个数字的值时所需的位数:
>>> bin(X), X.bit_length(), len(bin(X)) - 2
('0b1100011', 7, 7)
内置数值工具
- 内置数学函数:
pow
:计算幂abs
:计算绝对值sum
:求和round
:向上取整(四舍五入)max
:求最大值min
:求最小值
>>> pow(2, 4), 2 ** 4, 2.0 ** 4.0
(16, 16, 16.0)
>>> abs(-42.0), sum((1, 2, 3, 4))
(42.0, 10)
>>> min((1, 2, 3, 4)), max((1, 2, 3, 4))
(1, 4)
>>> round(2.56), round(2.46), round(2.567, 2) # round还可以指定小数的舍入位数
(3, 2, 2.57)
>>> '%.1f' % 2.567, '{0:.2f}'.format(2.567) # 字符串格式化也可使小数按位舍入
('2.6', '2.57')
内置函数位于一个隐藏的命名空间内,python会自动在这个命名空间中搜索名字,这个命名空间对应builtins
的标准库模块。
- 内置模块math:
>>> import math
>>> math.pi, math.e
(3.141592653589793, 2.718281828459045)
>>> math.sin(math.pi / 3), math.cos(math.pi / 3), math.tan(math.pi / 3)
(0.8660254037844386, 0.5000000000000001, 1.7320508075688767)
>>> math.sqrt(2)
1.4142135623730951
- 内置模块random
random提供了一系列的随机处理函数工具:
random.random
函数:返回一个随机的0到1之间的浮点数
random.randint
函数:返回一个两个数字之间的随机整数
random.choice
函数:从一个序列中随机挑选一项
random.shuffle
函数:随机打乱列表中的元素
>>> import random
>>> random.random()
0.6190454094520157
>>> random.random()
0.88053113013268
>>> random.randint(1, 10)
9
>>> random.randint(1, 10)
1
>>> random.choice(['a', 'b', 'c'])
'c'
>>> random.choice(['a', 'b', 'c'])
'b'
>>> abc = [ 'a', 'b', 'c']
>>> random.shuffle(abc)
>>> abc
['b', 'c', 'a']
>>> random.shuffle(abc)
>>> abc
['a', 'b', 'c']
2.2 小数类型
python中还有一种小数对象(Decimal
),小数对象位于decimal
模块中,创建时需要调用decimal
模块的Decimal
构造函数来创建小数,而不是通过字面量表达式来创建。
小数很像浮点数,但是小数有固定的位数和小数点,即小数是精度固定的浮点数。
小数基础知识
浮点数的运算缺乏精确性:
>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17
使用小数对象将使结果更加准确:
>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')
在表达式中使用不同精度的小数时,python会自动转换为最高的小数精度:
>>> Decimal('0.1') + Decimal('0.10') + Decimal('0.10') - Decimal('0.3')
Decimal('0.00')
也可以使用浮点数来创建小数对象,这一转换是精确的,但是有时候结果会产生庞大的小数位数:
Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3)
Decimal('2.775557561565156540423631668E-17')
设置全局小数精度
decimal模块还可设置全局的小数数值精度和舍入模式等:
>>> import decimal
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1428571428571428571428571429') # 小数的默认有效精度是28
# 设置小数精度
>>> decimal.getcontext().prec = 4
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1429')
# 设置舍入模式,decimal.ROUND_HALF_UP表示向上舍入,decimal.ROUND_HALF_DOWN表示向下舍入
>>> decimal.getcontext().rounding = decimal.ROUND_HALF_UP
>>> Decimal('3') / Decimal('2.2')
Decimal('1.364')
小数上下文管理器
可以使用with上下文管理语句创建小数的上下文管理器,这样在with语句中设置的精度将会在退出with语句后重置:
# 创建上下文管理器
>>> with decimal.localcontext() as ctx:
ctx.prec = 2
decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.14')
>>> decimal.Decimal(1) / decimal.Decimal(7)
Decimal('0.1429')
2.3 分数类型
python中还有分数类型(Fraction
),它实现了一个有理数对象,它显式地保留了一个分子和分母,从而避免了浮点数运算的不精确性。
分数基础知识
与小数类型类似,分数类型位于fractions
模块中,需要导入fractions
模块的构造函数Fraction
并传递一个分子和分母来产生一个分数:
>>> from fractions import Fraction
>>> Fraction(1, 3)
Fraction(1, 3)
>>> Fraction(4, 6)
Fraction(2, 3)
>>> x = Fraction(1, 3)
>>> y = Fraction(4, 6) # 分数会自动约分
>>> x
Fraction(1, 3)
>>> y
Fraction(2, 3)
>>> print(y)
2/3
分数对象也可以通过浮点数字符串来创建:
>>> Fraction('.25')
Fraction(1, 4)
>>> Fraction('1.25')
Fraction(5, 4)
一旦创建了分数对象,就可以用于平常的数学表达式中:
>>> x + y
Fraction(1, 1)
>>> x - y
Fraction(-1, 3)
>>> x * y
Fraction(2, 9)
分数转换和混用类型
- 浮点数转分数:浮点数对象有一个
as_integer_ratio()
方法,可以产生分子分母比;另外,分数有一个from_float
方法,可以接受一个浮点数返回对应的分数
>>> f = 0.25
>>> z = Fraction(*f.as_integer_ratio()) # *号是一种特殊的语法,它可以把一个元组展开成单独的参数
>>> z
Fraction(1, 4)
>>> Fraction.from_float(0.75)
Fraction(3, 4)
- 分数转浮点数:
float
函数可以直接将Fraction
对象转换成浮点数
>>> z
Fraction(1, 4)
>>> float(z)
0.25
表达式中允许分数和浮点数混合使用:
>>> x
Fraction(1, 3)
>>> x + 2 # Fraction + int -> Fraction
Fraction(7, 3)
>>> x + 2.0 # Fraction + float -> float
2.3333333333333335
>>> x + (1./3)
0.6666666666666666
>>> x + (4./3)
1.6666666666666665
>>> x + Fraction(4, 3) # Fraction + Fraction -> Fraction
Fraction(5, 3)
尽管可以把浮点数转换成分数,但是某种情况下,这么做会有不可避免的精度损失,因为这个数字在其最初的浮点数形式下就是不精确的,必要时,可以通过限制分母的最大值来简化这样的结果。
>>> (4 / 3).as_integer_ratio()
(6004799503160661, 4503599627370496)
>>> x
Fraction(1, 3)
>>> a = x + Fraction(*(4 / 3).as_integer_ratio())
>>> a
Fraction(22517998136852479, 13510798882111488)
>>> 22517998136852479 / 13510798882111488
1.6666666666666665
>>> a.limit_denominator(10)
Fraction(5, 3)