本篇文章为大家介绍Python中数字类型的抽象。
我们知道数学上,数字的类型可以由下面一个塔结构表示:
number 数
- complex 复数
- real 实数
- rational 有理数
- integer 整数
下面一级是上面一级的子类型。同样的,Python也为这些数字类型定义了对应的抽象,以便于针对不同类型的数字实现不同的行为。
Number是顶层抽象,并没有定义任何方法。如果需要判断是否是数字类型时,应当写为:
from numbers import Number
isinstance(x, Number)任何Number的子类,要自己实现哈希的方式。
复数抽象基类Complex继承自Number,提供了同内置类型complex一致的操作,包括:complex,.real,.imag,+,-,*,/,abs(),.conjugate,==和!=。下面分别介绍一下:
返回内置complex实例,将Complex子类对象退化为内建的复数对象。
实部与虚部@property
复数的符号,允许自定义+x和-x的行为
加法,乘法,除法与幂运算。需要注意的是,上面四类操作均需要定义对应的反向操作符,即__radd__,__rmul__等。
减法是不必定义的,复数相减可以写作加和的形式:x - y => x + -y
模运算与共轭运算。
比较是否相等。!=操作永远返回==的反意。
上述所有操作中,较难实现的是加减乘除等二元运算符,因为需要根据不同类型的数据实现不同的操作。需要注意的是,复数无法比较大小。
来看一下内建complex类型的操作:
a = 1 + 2j
b = complex(3, -4)
print(a.conjugate())
(1-2j)
print(a * b)
(11+2j)
print(a.real, a.imag)
1.0 2.0
print(b**a)
(-21.083139690689016+24.00021070941257j)复数下面是实数。实数继承自复数类,在其基础上增加了针对于实数的一些操作:
转换为内建float类型
这四个方法是专为实数设计的转换为整数的特殊方法。后三者比较常见,trunc方法是指将该实数向0方向取整,所以当该实数大于0时,trunc = floor;小于0时则trunc = ceil。方法调用需要利用数学库math
import math
a = 4.1
print(math.floor(a))
4
print(math.ceil(a))
5
print(math.trunc(a))
4
a = -4.1
print(math.floor(a))
-5
print(math.ceil(a))
-4
print(math.trunc(a))
-4事实上,如果将实数用int进行类型转换,其效果和trunc一致,所以我们应当优先使用int:
a = 4.1
b = -4.1
print(int(a))
4
print(int(b))
-4加减乘除操作在Complex中已经定义了。对于实数还存在这三种操作:除余,整除,取余。__divmod__能够同时获得商和余数;__floordiv__即整除//运算符;__mod__为百分号%运算符。需要注意的是,这些操作应当返回实数Real类型,而非整数类型。来看一下内建类型float怎么做的:
a = 4.5
q, r = divmod(a, 2)
print(q, r)
2.0 0.5
print(a // 2)
2.0
print(a % 2)
0.5实数是可以比较大小的。子类只需要实现<和<=两个抽象方法即可。
除此之外,Real还实现了部分Complex的抽象方法:
class Real(Complex):
def __complex__(self):
return complex(float(self))
@property
def real(self):
return +self
@property
def imag(self):
return 0
def conjugate(self):
return +self内建类型float注册为Real的虚拟子类。
有理数继承自实数Real。它自有的抽象方法是两个抽象属性:numerator分子和denominator分母。除此之外,Rational实现了Real中的__float__方法:
class Rational(Real):
def __float__(self):
return self.numerator / self.denominator整数则继承自有理数。Integral具有如下一些特别的抽象方法:
同__float__和__complex__一样,__int__用于将Integral子类对象转变为内建的int类型。
整数的__pow__相比于复数的幂运算,增加了一个modulus参数,允许整数求幂后直接进行模运算,当然,这样就不可使用二元运算符**来计算了。
整数还定义了位运算,包括移位、取反,以及按位与、或、异或等操作。
除此之外,整数实现了有理数中三个抽象方法:
class Integral(Rational):
def __float__(self):
return float(int(self))
@property
def numerator(self):
return +self
@property
def denominator(self):
return 1内建类型int注册为Integral的虚拟子类。