所有的类型都可以被比较、检测逻辑值、转换字符串,所有的数据类型都可进行数学运算。
逻辑值检测
任何数据类型或对象皆可进行逻辑值检测,默认情况下均被视为真值,除非对象或所属类重定义了bool()方法且返回False
或者是对象定义了len()方法且返回零。
以下是在逻辑检测时被视为假值的对象:
.被定义为假值的常量:None 和 False
.任何数值类型的零:0,0.0,0j,Decimal(0),Fraction(0,1)
.空的序列和多项集:'',(),{},set(),range(0)
Bool运算
Bool运算包括 and、or、not
,按照优先级排列not > and > or
运算 | 结果 | 注释 |
---|---|---|
x or y | 如果x为false,那么返回y,否则返回x | or为短路运算符,只有在第一个参数为假值时才会对第二个参数求值 |
x and y | 如果x为false,那么返回x,否则返回y | and同样是短路运算符,只有在第一个参数为真值时才会对第二个参数求值 |
not x | 如果x为false,那么返回True,否则返回False | 优先级比非布尔运算符低,因此 not a == b 会被解读为not (a==b) ,而a == not b 会造成语法错误 |
比较运算
Python中有八种比较运算符,优先级相同,但都比布尔运算优先级高,并且比较运算符可以任意串联。例如,x<y<=z
等价于 x< y and y <=z
,不同之处是前者y只被求值一次,后者会被求值两次,相同点是在x<y结果为假时z都不会被求值。
八种比较运算符如下:
运算符 | 含义 |
---|---|
< | 小于 |
<= | 小于或等于 |
> | 大于 |
>= | 大于等于 |
== | 等于 |
!= | 不等于 |
is | 对象标识 |
is not | 否定的对象标识 |
比较运算注意点
. 不同数字、不同类型对象比较时绝不会相等
. 函数类型仅支持简化形式比较
. <,<=,>,>= 运算符在比较复数和其它数字类型时,或在两个对象具有无法被比较的不同类型时,或在未定义次序的其他情况时,以上皆会产生TypeErroe
异常
. 不同标识类的实例比较,除非定义了eq()方法,否则不相等
. 类实例不能与相同类或其他实例或其它类型对象进行排序,除非定义了 it(),le(),gt(),ge()这些函数
. is
和 is not
无法自定义,可以被应用于任意两个对象不引发异常。
.in
和 not in
,与上面八种比较运算符具有相同优先级,但只能支持iterable(可迭代对象)或实现了contains()方法的类型
数字运算
所有的数字类型,除了复数类型,都支持下面的运算操作,所有数字运算的优先级都高于比较运算,以下按照优先级升序排列:
运算 | 含义 |
---|---|
+ | 两数之和 |
- | 两数之差 |
$ \times $ | 两数乘积 |
/ | 两数相除,结果返回商 |
// | 两数整除,结果返回商数 |
% | 两数相除结果取余数 |
-x | x取反 |
+x | x取正 |
abs(x) | x的绝对值 |
int(x) | 将x转换为整数 |
float(x) | 将x转换为浮点数 |
complex(re,im) | 一个带有实部re和虚部im的复数,im默认为0 |
c.conjugate() | 复数c的共轭 |
divmod(x,y) | 执行x//y x%y ,得到x被y除之后的商和余数 |
pow(x,y) | x的y次幂 |
x **y | 同样表示x的y次幂 |
invmod(x,y) | 对x模y取反 |
数字运算注意点:
. / 除法运算返回的永远是一个浮点数
.// 整除结果值是一个整数,但结果的类型不一定是int。 运算结果永远向负无穷方向舍入, 1//2 为0, (-1)//2 为-1,1//(-2)为-1,(-1)//(-2)为0。
. % 不能用于复数
. int() 若从浮点数转换为整数会被舍入或被截断,原因在前面文章数字类型中提到过,因为二进制浮点数问题
数字类型还能进行数学函数运算,具体会在后面math和cmath模块讲到。
整数类型按位运算
按位运算只对整数有意义,按位运算优先级低于数字运算,高于比较运算,但一元运算~
与其它一元算术运算符优先级相同。
运算 | 含义 | 说明 | |
---|---|---|---|
x\ | y | x和y按位或 | |
x^y | x和y按位异或 | ||
x&y | x和y按位与 | ||
x<<n | x左移n位 | 负的移位会引发ValueError,左移n位等价于不带溢出检测的乘以pow(2,n) | |
x>>n | x右移n位 | 负的移位同样会引发ValueErroe,右移n位等价于不带溢出检测的除以pow(2,n) | |
~x | x按位取反 |
数字类型的哈希运算
不同数字类型的两个数,要做== 比较运算时,必须转成哈希值,即hash(x)==hash(y)。为便于在各种数字类型上实现并保证效率,Python对数字类型的哈希运算是基于任意有理数定义统一的数学函数,本质上hash()是通过以一个固定质数P进行P降模。P的值在 Python 中可以 sys.hash_info
的 modulus
属性的形式被访问。
CPython implementation detail: 所用质数设定,在 C long 为 32 位的机器上 P = 2**31 - 1
而在 C long 为 64 位的机器上 P = 2**61 - 1
运算规则如下:
- 如果
x = m / n
是一个非负比例数,且n
不能被P
整除,则定义hash(x)
为m * invmod(n, P) % P
。 - 如果
x = m / n
是一个非负比例数,且n
能被P
整除(但m
不能)则n
不能对P
降模,以上规则不适用;在此情况下则定义hash(x)
为常数值sys.hash_info.inf
。 - 如果
x = m / n
是一个负比例数,则定义hash(x)
为-hash(-x)
。 如果结果哈希值为-1
则将其替换为-2
。 - 特定值
sys.hash_info.inf
,-sys.hash_info.inf
和sys.hash_info.nan
被用作正无穷、负无穷和空值(所分别对应的)哈希值。 (所有可哈希的空值都具有相同的哈希值) - 对于一个
complex
值z
,会通过计算hash(z.real) + sys.hash_info.imag * hash(z.imag)
将实部和虚部的哈希值结合起来,并进行降模2**sys.hash_info.width
以使其处于range(-2**(sys.hash_info.width - 1), 2**(sys.hash_info.width - 1))
范围之内。 同样地,如果结果为-1
则将其替换为-2
为了更好的理解运算规则,用代码实现如下:
对分数求哈希值:
>>> import sys,math
>>> def hash_fraction(m,n):
'''计算比例数m/n的哈希值,m和n为整数,n为正数'''
P = sys.hash_info.modulus
#去掉P的公因数,除非m和n互质
while m%P == n%P ==0:
m,n = m//P, n//P
#如果n能被P整除,hash值为固定值
if n % P == 0:
hash_value = sys.hash_info.inf
else:
#如果n不能被P整除,则对P进行降模处理
hash_value = (abs(m)%P)*pow(n,P-2,P)%P
#判断m是否是负数,对负数求hash
if m < 0:
hash_value = -hash_value
if hash_value == -1:
hash_value = -2
return hash_value
对float浮点数类型求哈希值:
>>> def hash_float(x):
#计算浮点数x的哈希值
if math.isnan(x):
return sys.hash_info.nan
elif math.isinf(x):
return sys.hash_info.inf if x > 0 else -sys.hash_info.inf
else:
return hash_fraction(*x.as_integer_ratio())
对复数类型求哈希值:
#计算复数z的哈希值
hash_value = hash_float(z.real) + sys.hash_info.imag * hash_float(z.imag)
M = 2 **(sys.hash_info.width - 1)
hash_value = (hash_value & (M-1)) - (hash_value&M)
if hash_value == -1:
hash_value = -2
return hash_value
Decimal运算实例
Decimal 进行 $+ 、- 、\times 、/$ 运算
>>> data = list(map(Decimal, '1.34 1.87 3.45 2.35 1.00 0.03 9.25'.split()))
>>> sum (data)
Decimal('19.29')
>>> min(data)
Decimal('0.03')
>>> max(data)
Decimal('9.25')
>>> min(data)
Decimal('0.03')
>>> a,b,c = data[:3]
>>> a * 5
Decimal('6.70')
>>> a * b
Decimal('2.5058')
>>> c % a
Decimal('0.77')
>>> a + b + c
Decimal('6.66')
>>> a - b
Decimal('-0.53')
>>>
当余数运算%应用于Decimal对象时,结果的符号是被除数的符号,而不是除数的符号
>>> -5 % 8
3
>>> Decimal(-5) % Decimal(8)
Decimal('-5')
>>> Decimal(8) % Decimal(-5)
Decimal('3')
同样Decimal也可以进行一些数学函数运算
>>> Decimal(2).sqrt()
Decimal('1.41421')
>>> Decimal(1).exp()
Decimal('2.71828')
>>> Decimal(10).ln
<built-in method ln of decimal.Decimal object at 0x1073b04a8>
>>> Decimal(10).ln()
Decimal('2.30259')
>>> Decimal('10').log10()
Decimal('1')
关于四舍五入,Decimal的quantize()方法可以将数字四舍五入为固定函数
>>> Decimal('7.325').quantize(Decimal('0.01'), rounding=ROUND_DOWN)
Decimal('7.32')
>>> Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8')
Fraction运算实例
Fraction同样可以进行$+、-、\times /$ 四则运算和%运算等
>>> from fractions import Fraction
>>> import math
>>> Fraction(2,3) + Fraction(3,5)
Fraction(19, 15)
>>> Fraction(2,3) - Fraction(3,5)
Fraction(1, 15)
>>> Fraction(2,3) * Fraction(3,5)
Fraction(2, 5)
>>> Fraction(2,3) / Fraction(3,5)
Fraction(10, 9)
>>> Fraction(2,3) % Fraction(-3, 5)
Fraction(-8, 15)
>>> Fraction(2,3) % Fraction(3,5)
Fraction(1, 15)
Fraction没有sqrt()、exp()等函数方法。
参考文献: