numbers --- Các lớp cơ sở trừu tượng bằng số¶
Source code: Lib/numbers.py
Mô-đun numbers (PEP 3141) xác định hệ thống phân cấp của abstract base classes số để xác định dần dần nhiều hoạt động hơn. Không có loại nào được xác định trong mô-đun này nhằm mục đích khởi tạo.
- class numbers.Number¶
Gốc của hệ thống phân cấp số. Nếu bạn chỉ muốn kiểm tra xem một đối số x có phải là một số hay không mà không quan tâm đến loại nào, hãy sử dụng
isinstance(x, Number).
Tháp số¶
- class numbers.Complex¶
Các lớp con của loại này mô tả các số phức và bao gồm các phép toán hoạt động trên loại
complextích hợp sẵn. Đó là: chuyển đổi sangcomplexvàbool,real,imag,+,-,*,/,**,abs(),conjugate(),==và!=. Tất cả ngoại trừ-và!=đều trừu tượng.- real¶
Trừu tượng. Lấy thành phần thực của số này.
- imag¶
Trừu tượng. Lấy thành phần ảo của số này.
- abstractmethod conjugate()¶
Trừu tượng. Trả về liên hợp phức. Ví dụ:
(1+3j).conjugate() == (1-3j).
- class numbers.Real¶
Đối với
Complex,Realthêm các phép toán hoạt động trên số thực.Nói tóm lại, đó là: chuyển đổi sang
float,math.trunc(),round(),math.floor(),math.ceil(),divmod(),//,%,<,<=,>và>=.Real cũng cung cấp các giá trị mặc định cho
complex(),real,imagvàconjugate().
- class numbers.Rational¶
Phân loại
Realvà thêm các thuộc tínhnumeratorvàdenominator. Nó cũng cung cấp một mặc định chofloat().Các giá trị
numeratorvàdenominatorphải là phiên bản củaIntegralvà phải ở mức thấp nhất vớidenominatordương.- numerator¶
Trừu tượng. Tử số của số hữu tỉ này.
- denominator¶
Trừu tượng. Mẫu số của số hữu tỉ này.
Lưu ý dành cho người triển khai kiểu¶
Người triển khai nên cẩn thận để làm cho các số bằng nhau bằng nhau và băm chúng thành cùng một giá trị. Điều này có thể tinh tế nếu có hai phần mở rộng khác nhau của số thực. Ví dụ: fractions.Fraction triển khai hash() như sau:
chắc chắn __hash__(tự):
nếu self.mẫu số == 1:
số nguyên # Get đúng.
hàm băm trả về (self.numerator)
# Expensive kiểm tra, nhưng chắc chắn là đúng.
nếu tự == float(tự):
trả về hàm băm(float(self))
khác:
hàm băm của bộ # Use để tránh tỷ lệ va chạm cao trên
phân số # simple.
hàm băm trả về((self.numerator, self.mẫu số))
Thêm nhiều số ABC hơn¶
Tất nhiên, có nhiều ABC khả thi hơn cho các số và đây sẽ là một hệ thống phân cấp kém nếu nó loại trừ khả năng thêm các số đó. Bạn có thể thêm MyFoo giữa Complex và Real bằng:
lớp MyFoo(Phức tạp): ...
MyFoo.register(Thực)
Thực hiện các phép tính số học¶
Chúng tôi muốn triển khai các phép toán số học để các phép toán ở chế độ hỗn hợp gọi một triển khai mà tác giả biết về loại của cả hai đối số hoặc chuyển đổi cả hai thành loại được xây dựng gần nhất và thực hiện thao tác ở đó. Đối với các kiểu con của Integral, điều này có nghĩa là __add__() và __radd__() phải được xác định là:
lớp MyIntegral(Tích phân):
def __add__(bản thân, người khác):
nếu isinstance(other, MyIntegral):
trả về do_my_adding_stuff(self, other)
Elif isinstance(other, OtherTypeIKnowAbout):
trả về do_my_other_adding_stuff(self, other)
khác:
trả về Chưa thực hiện
def __radd__(bản thân, người khác):
nếu isinstance(other, MyIntegral):
trả về do_my_adding_stuff(other, self)
Elif isinstance(other, OtherTypeIKnowAbout):
trả về do_my_other_adding_stuff(other, self)
Elif isinstance(khác, Tích phân):
trả về int(other) + int(self)
Elif isinstance(other, Real):
trả về float(other) + float(self)
Elif isinstance(other, Complex):
trả về phức tạp (khác) + phức tạp (tự)
khác:
trả về Chưa thực hiện
Có 5 trường hợp khác nhau cho thao tác kiểu hỗn hợp trên các lớp con của Complex. Tôi sẽ gọi tất cả các mã ở trên không đề cập đến MyIntegral và OtherTypeIKnowAbout là "bản soạn sẵn". a sẽ là một phiên bản của A, là một kiểu con của Complex (a : A <: Complex) và b : B <: Complex. Tôi sẽ xem xét a + b:
Nếu
Axác định__add__()chấp nhậnbthì tất cả đều ổn.Nếu
Aquay trở lại mã soạn sẵn và trả về giá trị từ__add__(), thì chúng ta sẽ bỏ lỡ khả năngBđịnh nghĩa một__radd__()thông minh hơn, vì vậy mã soạn sẵn sẽ trả vềNotImplementedtừ__add__(). (HoặcAcó thể không triển khai__add__().)Sau đó,
__radd__()củaBsẽ có cơ hội. Nếu nó chấp nhậna, tất cả đều ổn.Nếu nó rơi trở lại bản soạn sẵn thì không còn phương pháp nào khả thi nữa để thử, vì vậy đây là nơi triển khai mặc định.
Nếu
B <: A, Python thửB.__radd__trướcA.__add__. Điều này không sao cả, vì nó được triển khai với kiến thức vềAnên nó có thể xử lý các trường hợp đó trước khi ủy quyền choComplex.
Nếu A <: Complex và B <: Real không chia sẻ bất kỳ kiến thức nào khác thì thao tác chia sẻ thích hợp là thao tác liên quan đến complex tích hợp và cả __radd__() đều ở đó, vì vậy a+b == b+a.
Bởi vì hầu hết các thao tác trên bất kỳ loại nhất định nào sẽ rất giống nhau, nên có thể hữu ích khi xác định hàm trợ giúp tạo ra các phiên bản tiến và lùi của bất kỳ toán tử nhất định nào. Ví dụ: fractions.Fraction sử dụng:
def _operator_fallbacks(monomorphic_operator, fallback_operator):
def về phía trước (a, b):
if isinstance(b, (int, Fraction)):
trả về monomorphic_operator(a, b)
Elif isinstance(b, float):
trả về fallback_operator(float(a), b)
Elif isinstance(b, complex):
trả về fallback_operator(complex(a), b)
khác:
trả về Chưa thực hiện
chuyển tiếp.__name__ = '__' + fallback_operator.__name__ + '__'
chuyển tiếp.__doc__ = monomorphic_operator.__doc__
def đảo ngược (b, a):
nếu isinstance(a, Rational):
số nguyên # Includes.
trả về monomorphic_operator(a, b)
Elif isinstance(a, Real):
trả về fallback_operator(float(a), float(b))
Elif isinstance(a, Complex):
trả về fallback_operator(complex(a), complex(b))
khác:
trả về Chưa thực hiện
đảo ngược.__name__ = '__r' + fallback_operator.__name__ + '__'
đảo ngược.__doc__ = monomorphic_operator.__doc__
quay về phía trước, ngược lại
def _add(a, b):
"""a + b"""
trả về Phân số(a.tử số * b.mẫu số +
b.tử số * a.mẫu số,
a.mẫu số * b.mẫu số)
__add__, __radd__ = _operator_fallbacks(_add, operator.add)
# ...