Pythonの数字は何ですか?

時間を費やす: Pythonでは、明示的な型変換を行わなくても、さまざまな種類の数値を算術演算に直接使用できます。ただし、Pythonの数値は同じ抽象基本クラスから派生した特殊な種類のオブジェクトであるため、その「暗黙的な型変換」は他の言語とは異なる場合があります。 [前回の記事](http://mp.weixin.qq.com/s?__biz=MzUyOTk2MTcwNg==&mid=2247486538&idx=1&sn=72eb29bfd6d5079761c9752846992b64&chksm=fa584bcfcd2fc2d9415a1a1f905bd8d1e9530b9e6a889ac41f6e7d80460108b03031a807d9e1&scene=21#wechat_redirect)では、Pythonの数値の計算について説明した後、「Pythonの数値オブジェクトとは」というトピックを探求したかったので、このPEPを翻訳しました。お役に立てば幸いです。 。


PEPの元のテキスト: https://www.python.org/dev/peps/pep-3141

PEPタイトル: PEP3141-番号のタイプ階層

PEP作成者: Jeffrey Yasskin

作成日: 2007-04-23

翻訳者:猫の下のエンドウ豆@Python猫公号

PEP翻訳計画: https://github.com/chinesehuazhou/peps-cn

まとめ

この提案は、数のようなクラスを表すために、抽象基本クラス(ABC)(PEP 3119)の階層構造を定義します。これは、Number:> Complex:> Real:> Rational:> Integralの階層構造を提案します。ここで、A:> Bは「AはBのスーパークラス」を意味します。この階層は、Schemeの数値タワーに触発されています。 (注釈:数値-複素数-実数-合理的な数値-整数)

基本

数値をパラメーターとして受け取る関数は、これらの数値の属性を判別でき、数値のタイプに基づいて、つまりパラメーターのタイプに基づいて、オーバーロードできるかどうか、いつオーバーロードする必要があるかを判別できる必要があります。

たとえば、sliceではパラメータが Integralsである必要がありますが、 mathモジュールの関数ではパラメータが Realである必要があります。

仕様

このPEPは、一連の抽象基本クラス(抽象基本クラス)を指定し、特定のメソッドを実装するための一般的な戦略を提案します。これはPEP3119の用語を使用していますが、階層は特定のクラスのセットのシステムアプローチに意味をなすように意図されています。

標準ライブラリでの型チェックでは、特定の組み込み型ではなく、これらのクラスを使用する必要があります。

数値クラス

まず、人々が想像する数のタイプの漠然とした概念であるNumberクラスから始めます。このクラスはオーバーロードにのみ使用され、操作は提供しません。

classNumber(metaclass=ABCMeta): pass

複素数のほとんどの実装はハッシュ可能ですが、それに依存する必要がある場合は、明示的に確認する必要があります。この階層は可変数をサポートします。

classComplex(Number):"""Complex defines the operations that work on the builtin complex type.

 In short, those are: conversion to complex,bool(),.real,.imag,+,-,*,/,**,abs(),.conjugate(),==, and !=.

 If it is given heterogenous arguments, and doesn't have special
 knowledge about them, it should fall back to the builtin complex
 type as described below."""

 @ abstractmethod
 def __complex__(self):"""Return a builtin complex instance."""

 def __bool__(self):"""True if self != 0."""return self !=0

 @ abstractproperty
 def real(self):"""Retrieve the real component ofthis number.

  This should subclass Real."""
  raise NotImplementedError

 @ abstractproperty
 def imag(self):"""Retrieve the real component ofthis number.

  This should subclass Real."""
  raise NotImplementedError

 @ abstractmethod
 def __add__(self, other):
  raise NotImplementedError

 @ abstractmethod
 def __radd__(self, other):
  raise NotImplementedError

 @ abstractmethod
 def __neg__(self):
  raise NotImplementedError

 def __pos__(self):"""Coerces self to whatever class defines the method."""
  raise NotImplementedError

 def __sub__(self, other):return self +-other

 def __rsub__(self, other):return-self + other

 @ abstractmethod
 def __mul__(self, other):
  raise NotImplementedError

 @ abstractmethod
 def __rmul__(self, other):
  raise NotImplementedError

 @ abstractmethod
 def __div__(self, other):"""a/b; should promote to float or complex when necessary."""
  raise NotImplementedError

 @ abstractmethod
 def __rdiv__(self, other):
  raise NotImplementedError

 @ abstractmethod
 def __pow__(self, exponent):"""a**b; should promote to float or complex when necessary."""
  raise NotImplementedError

 @ abstractmethod
 def __rpow__(self, base):
  raise NotImplementedError

 @ abstractmethod
 def __abs__(self):"""Returns the Real distance from 0."""
  raise NotImplementedError

 @ abstractmethod
 def conjugate(self):"""(x+y*i).conjugate() returns (x-y*i)."""
  raise NotImplementedError

 @ abstractmethod
 def __eq__(self, other):
  raise NotImplementedError

 # __ ne__ is inherited from object and negates whatever __eq__ does.

Real抽象基本クラスは、実数軸上の値を表し、組み込みの float操作をサポートします。 NaNを除いて、実際の番号は完全に順序付けられています(このPEPは基本的にそれを考慮していません)。

classReal(Complex):"""To Complex, Real adds the operations that work on real numbers.

 In short, those are: conversion to float,trunc(), math.floor(),
 math.ceil(),round(),divmod(),//, %, <, <=, >, and >=.

 Real also provides defaults for some of the derived operations."""

 # XXX What to do about the __int__ implementation that's
 # currently present on float?  Get rid of it?

 @ abstractmethod
 def __float__(self):"""Any Real can be converted to a native float object."""
  raise NotImplementedError

 @ abstractmethod
 def __trunc__(self):"""Truncates self to an Integral.

  Returns an Integral i such that:* i>=0 iff self>0;*abs(i)<=abs(self);*for any Integral j satisfying the first two conditions,abs(i)>=abs(j)[i.e. i has "maximal" abs among those].
  i.e."truncate towards 0"."""
  raise NotImplementedError

 @ abstractmethod
 def __floor__(self):"""Finds the greatest Integral <= self."""
  raise NotImplementedError

 @ abstractmethod
 def __ceil__(self):"""Finds the least Integral >= self."""
  raise NotImplementedError

 @ abstractmethod
 def __round__(self, ndigits:Integral=None):"""Rounds self to ndigits decimal places, defaulting to 0.

  If ndigits is omitted or None, returns an Integral,
  otherwise returns a Real, preferably of the same type as
  self. Types may choose which direction to round half. For
  example, float rounds half toward even."""
  raise NotImplementedError

 def __divmod__(self, other):"""The pair(self // other, self % other).

  Sometimes this can be computed faster than the pair of
  operations."""
  return(self // other, self % other)

 def __rdivmod__(self, other):"""The pair(self // other, self % other).

  Sometimes this can be computed faster than the pair of
  operations."""
  return(other // self, other % self)

 @ abstractmethod
 def __floordiv__(self, other):"""The floor() of self/other. Integral."""
  raise NotImplementedError

 @ abstractmethod
 def __rfloordiv__(self, other):"""The floor() of other/self."""
  raise NotImplementedError

 @ abstractmethod
 def __mod__(self, other):"""self % other

  See
  https://mail.python.org/pipermail/python-3000/2006-May/001735.html
  and consider using "self/other - trunc(self/other)"
  instead if you're worried about round-off errors."""
  raise NotImplementedError

 @ abstractmethod
 def __rmod__(self, other):"""other % self"""
  raise NotImplementedError

 @ abstractmethod
 def __lt__(self, other):"""< on Reals defines a total ordering, except perhaps for NaN."""
  raise NotImplementedError

 @ abstractmethod
 def __le__(self, other):
  raise NotImplementedError

 # __ gt__ and __ge__ are automatically done by reversing the arguments.
 # ( But __le__ is not computed as the opposite of __gt__!)

 # Concrete implementations of Complex abstract methods.
 # Subclasses may override these, but don't have to.

 def __complex__(self):returncomplex(float(self))

 @ property
 def real(self):return+self

 @ property
 def imag(self):return0

 def conjugate(self):"""Conjugate is a no-op for Reals."""return+self

Demo / classes / Rat.pyを整理し、Rational.pyにアップグレードして、標準ライブラリに追加する必要があります。次に、有理数の抽象基本クラス(Rational)を実装します。

classRational(Real, Exact):""".numerator and .denominator should be in lowest terms."""

 @ abstractproperty
 def numerator(self):
  raise NotImplementedError

 @ abstractproperty
 def denominator(self):
  raise NotImplementedError

 # Concrete implementation of Real's conversion to float.
 # ( This invokes Integer.__div__().)

 def __float__(self):return self.numerator / self.denominator

最後に、整数クラス:

classIntegral(Rational):"""Integral adds a conversion to int and the bit-string operations."""

 @ abstractmethod
 def __int__(self):
  raise NotImplementedError

 def __index__(self):"""__index__() exists because float has __int__()."""returnint(self)

 def __lshift__(self, other):returnint(self)<<int(other)

 def __rlshift__(self, other):returnint(other)<<int(self)

 def __rshift__(self, other):returnint(self)>>int(other)

 def __rrshift__(self, other):returnint(other)>>int(self)

 def __and__(self, other):returnint(self)&int(other)

 def __rand__(self, other):returnint(other)&int(self)

 def __xor__(self, other):returnint(self)^int(other)

 def __rxor__(self, other):returnint(other)^int(self)

 def __or__(self, other):returnint(self)|int(other)

 def __ror__(self, other):returnint(other)|int(self)

 def __invert__(self):return~int(self)

 # Concrete implementations of Rational and Real abstract methods.
 def __float__(self):"""float(self) == float(int(self))"""returnfloat(int(self))

 @ property
 def numerator(self):"""Integers are their own numerators."""return+self

 @ property
 def denominator(self):"""Integers have a denominator of 1."""return1

計算と__magic__メソッドの変更

floatからintへの(正確にはRealからIntegralへの)正確な縮小をサポートするために、対応するライブラリ関数から呼び出すことができる次の新しい__magic__メソッドを提案します。これらのメソッドはすべて、RealではなくIntergralを返します。

  1. __ trunc __(self):新しい組み込みtrunc(x)で呼び出され、xに最も近い0からxまでの積分を返します。
  2. __ floor __(self):math.floor(x)で呼び出され、最大のIntegral <= xを返します。
  3. __ ceil __(self):math.ceil(x)で呼び出され、最小の積分> = xを返します。
  4. __ round __(self):round(x)で呼び出され、xに最も近い積分を返し、選択したタイプに従って切り上げます。バージョン3.0から、浮動小数点数は偶数端に丸められます。 (注釈:round(2.5)は2に等しく、round(3.5)は4に等しい)。また、round(x、ndigits)によって呼び出される、2つのパラメーター__round __(self、ndigits)を持つバージョンもありますが、Realを返します。

バージョン2.6では、math.floor、math.ceil、およびroundは引き続き浮動小数点数を返します。

floatのint()変換は、trunc()と同等です。一般的に、int()の変換では、最初に__int __()が試行され、見つからない場合は__trunc __()が試行されます。

complex .__ {divmod、mod、floordiv、int、float} __も消えました。紛らわしいポーターを助けるために良いエラーメッセージを提供するのは良いことですが、もっと重要なことに、それはhelp(complex)に表示されません。

タイプ実装者向けの説明

実装者は、等しい数を等しくし、それらを同じ値にハッシュするように注意する必要があります。実数に2つの異なる拡張子がある場合、これは微妙になる可能性があります。たとえば、複合型は次のようにhash()を合理的に実装できます。

def __hash__(self):returnhash(complex(self))

ただし、組み込みの複素数の範囲または精度を超えるすべての値に注意する必要があります。

デジタル抽象基本クラスをさらに追加

もちろん、数字はより抽象的な基本クラスを持っているかもしれません。これらの数字を追加する可能性が除外されている場合、これは悪い階層になります。次のメソッドを使用して、ComplexとRealの間にMyFooを追加できます。

classMyFoo(Complex):...
MyFoo.register(Real)

算術演算を実装する

混合モード操作で、呼び出し元が2つのパラメータータイプの処理方法を知っているか、両方が最も近い組み込みタイプに変換されてそれに応じて操作されるように、算術演算を実装したいと考えています。

Integralのサブタイプの場合、これは__add__および__radd__を次のように定義する必要があることを意味します。

classMyIntegral(Integral):

 def __add__(self, other):ifisinstance(other, MyIntegral):returndo_my_adding_stuff(self, other)
  elif isinstance(other, OtherTypeIKnowAbout):returndo_my_other_adding_stuff(self, other)else:return NotImplemented

 def __radd__(self, other):ifisinstance(other, MyIntegral):returndo_my_adding_stuff(other, self)
  elif isinstance(other, OtherTypeIKnowAbout):returndo_my_other_adding_stuff(other, self)
  elif isinstance(other, Integral):returnint(other)+int(self)
  elif isinstance(other, Real):returnfloat(other)+float(self)
  elif isinstance(other, Complex):returncomplex(other)+complex(self)else:return NotImplemented

複雑なサブクラスでの混合型操作には、5つの異なる状況があります。 MyIntegralとOtherTypeIKnowAboutを含まない上記のすべてのコードを「ボイラープレート」と呼びます。

aはAのインスタンスであり、 Complex(a:A &lt;:Complex)および b:B &lt;:Complexのサブタイプです。 a + bの場合、私はこれを考慮します。

  1. Aがbを受け入れる__add__を定義している場合、問題はありません。
  2. Aがボイラープレートコードブランチに移動し、__ add__から値を返す場合、Bに対してよりスマートな__radd__を定義する可能性を見逃しているため、ボイラープレートは__add__から開始する必要があります。 NotImplementedを返します。 (または、Aは__add__を実装しない場合があります)
  3. その後、Bの__radd__の機会が訪れました。を受け入れる場合は問題ありません。
  4. ボイラープレートブランチに行く場合、方法がないので、デフォルトの実装が必要です。
  5. B <:Aの場合、PythonはA .__ add__の前にB .__ radd__を試行します。これは、Aに基づいて実装されているため、Complexに委任する前にこれらのインスタンスを処理できるため、可能です。

A <:ComplexとB <:Realに他の関係がない場合、適切な共有操作は組み込みの複合番号の操作であり、それらの__radd__が含まれているため、a + b == b + aです。 (注釈:これらの段落をあまり明確に読んでいませんでした。おそらく正しく翻訳されていませんでした)

拒否された提案

このPEPの初期バージョンは、Haskell Numeric Preludeに触発された代数階層を定義します。これには、MonoidUnderPlus、AdditiveGroup、Ring、およびFieldが含まれ、数値を取得する前に、他のいくつかの可能な代数タイプがあります。

これがベクトルや行列を使用する人々に役立つことを当初は望んでいましたが、NumPyコミュニティは実際にはそれに興味がなく、xがX <:MonoidUnderPlusのインスタンスであり、yがY <:MonoidUnderPlusのインスタンスであっても問題が発生しました。 、X + yはまだ機能しない可能性があります。

次に、GaussianIntegerやZ / nZなど、数値の分岐構造をさらに提供します。これらは複雑になる可能性がありますが、必ずしも「除算」などの操作をサポートするとは限りません。

コミュニティは、これはPythonには複雑すぎると考えているため、提案の範囲を狭めて、Schemeデジタルタワーに近づけます。

10進タイプ

筆者との協議の結果、現時点ではデジタルタワーの一部としてデシマルタイプを使用しないことを決定しました。

参照

1、 抽象基本クラスの概要:http://www.python.org/dev/peps/pep-3119/

2、 Python 3クラスツリーかもしれませんか? Bill JanssenのWikiページ:http://wiki.python.org/moin/AbstractBaseClasses

3、 NumericPrelude:数値型クラスの実験的な代替階層:http://darcs.haskell.org/numericprelude/docs/html/index.html

4、 スキームデジタルタワー:https://groups.csail.mit.edu/mac/ftpdir/scheme-reports/r5rs-html/r5rs_8.html#SEC50

(注釈:翻訳後、「PEP中国語翻訳プロジェクト」に翻訳が含まれていて、翻訳の一部が同じではないことがわかりました。読者はクリックして元のテキストを読み、比較して読むことができます。)

ありがとう

最初にこのPEPの作成を勧めてくれたニール・ノーウィッツ、厄介なコミュニティは代数の概念をあまり気にしていないことを指摘してくれたトラビス・オリファント、スキームがそれを行ったことを思い出させてくれたアラン・アイザック、そしてこのセットの改善を支援してくれたメールグループのギド・ヴァン・ロッサムなどに感謝します。概念。

**Copyright **

ドキュメントはパブリックドメインに配置されました。

ソースファイル:https://github.com/python/peps/blob/master/pep-3141.txt

Recommended Posts

Pythonの数字は何ですか?
pythonでファイルを開く方法は何ですか
pythonの必須パラメーターは何ですか
pythonのWeb開発フレームワークとは何ですか
python言語の利点は何ですか
pythonのタブキーはどういう意味ですか
pythonクラスの属性とは何ですか
pythonのイントロスペクションとは何ですか
pythonのオブジェクト指向とは何ですか
Pythonの無限ループに必要な条件
pythonがmysqlに接続するための方法は何ですか
Pythonデータの視覚化:Pythonの有名人は誰ですか?
pythonでのwheelの使用法
pythonのリスト内包表記とは何ですか
Pythonでのrc1の意味
pythonのdefは何をしますか
Pythonの用途は何ですか
pythonで数値をフィルタリングする方法
Pythonにはいくつかのキーワードがあります
npはpythonで何をしますか
Pythonのモジュールについて話す
pythonでのタプルの使用法
pythonでのrbの意味を理解する
Python3クローラーでのAjaxの使用
python変数の範囲は何ですか
Pythonの匿名関数とは何ですか
python開発の見通しは何ですか
Pythonのシーケンステーブルとは
pythonの関数本体は何ですか
Pythonはリスト内の要素をランダムにシャッフルします
pythonの関数
2.1 Pythonインタープリター(pythonインタープリター)
pythonでround関数を使用する方法
Pythonマルチスレッドのリストを詳しく説明する
Pythonでzip関数を使用する方法
Pythonでの歩留まりを理解するための記事
PythonはDoudizhuでカードのシャッフルを実装します
pythonでのリストの意味と使用法
pythonでformat関数を使用する方法
pythonに最初に精通した、pythonの文法規則
pythonとpycharmの違いは何ですか
ubuntuでpythonをアンインストールした結果、非常に
ダウンロードしたモジュールをpythonでインストールする方法
Pythonで型を判断するための最良の方法
同期Pythonと非同期Pythonの違いは何ですか?
03.Pythonエントリの演算子
Pythonでできること
Pythonの結合関数
pythonでステートメントを印刷する
Pythonでのパッケージの導入を理解する方法
pythonで番号のリストを理解する方法
Pythonでの同時リクエスト
Ubuntuにpythonをインストールする
Pythonの基盤を統合する(2)
Pythonでのコンテキスト管理
pythonの算術演算子
pythonでguiを書く
PythonでのMongoDBの使用
PythonのStr文字列
歴史上初めて、PythonはJavaを上回りました!
Pythonでの計算ジオメトリ