1. ホーム
  2. パイソン

[解決済み】なぜPythonには符号関数がないのですか?

2022-03-29 07:10:05

質問

なぜPythonには sign 関数があります。これは abs ビルトイン(私が考える sign の姉妹)、しかし sign .

Python 2.6では、さらに copysign 関数があります。 数学 ) が、符号がない。なぜわざわざ copysign(x,y) を書けばいいだけなのに sign を取得し、その後に copysign から直接 abs(x) * sign(y) ? 後者では、xにyの符号を付けるという、より明確な表現になりますが、copysignでは、xにyの符号を付けるのか、yにxの符号を付けるのかを覚えておかなければなりません!?

明らかに sign(x) を超えるものを提供するものではありません。 cmp(x,0) しかし、これもずっと読みやすいでしょう(そして、pythonのような非常に読みやすい言語にとって、これは大きなプラスだったでしょう)。

もし私がPythonのデザイナーなら、その反対を選ぶでしょう。 cmp をビルトインし sign . を必要とする場合 cmp(x,y) を実行すればよいのです。 sign(x-y) (あるいは、数値以外のものであれば、x>y で済ませることもできます - もちろん、これには sorted は、整数のコンパレータの代わりにブーリアンを受け入れます)。これはまた、より明確であろう:正 x>y (一方 cmp を使用する場合、その規約を覚えておく必要があります。 最初 大きい が、その逆もあり得る)。もちろん cmp は、他の理由でも意味があります (例えば、数値以外のものをソートするときや、ソートを安定させたいときなど、単なるブール値では不可能な場合です)。

そこで質問ですが、Pythonの設計者はなぜ sign 関数を言語から排除しているのでしょうか?なぜわざわざ copysign であって、その親である sign ?

何か見落としているのでしょうか?

EDIT - ピーターハンセンコメントの後。 使っていないのは結構ですが、pythonを何に使っているのかが書かれていませんね。私は7年間パイソンを使っていて、数え切れないほどパイソンが必要になったことがあり、最後がラクダの背を折るわらでした

確かにcmpを渡すことはできますが、渡す必要があったのは9割がた次のようなイディオムでした。 lambda x,y: cmp(score(x),score(y)) であれば、signで問題なく動作したはずです。

最後に、以下のことに同意していただけると幸いです。 sign よりも有用であろう。 copysign というわけで、仮にあなたの見解を信じたとしても、なぜわざわざsignの代わりにそれを数学で定義する必要があるのでしょうか?どうしてcopysignがsignよりずっと便利なのでしょうか?

どうすれば解決するの?

EDITです。

確かに パッチ を含む sign() 数学 に同意していなかったため、受け入れられませんでした。 は、すべてのエッジケースで何を返すべきでしょうか。 (+/-0, +/-nan, etc)

そこで、彼らはcopysignのみを実装することにしたのですが、これは(より冗長ではありますが)以下のようなことが可能です。 エッジケースで望ましい動作をエンドユーザーに委ねるために使われる - どの を呼び出す必要がある場合があります。 cmp(x,0) .


なぜ内蔵でないのかわかりませんが、ちょっと考えてみました。

copysign(x,y):
Return x with the sign of y.

最も重要なのは copysign のスーパーセットです。 sign ! 呼び出し copysign を x=1 とした場合は sign 関数を使用します。 ということは、単に copysign 忘れてください .

>>> math.copysign(1, -4)
-1.0
>>> math.copysign(1, 3)
1.0

引数をまるまる2つ渡すのが嫌になった場合は、以下のように実装します。 sign この方法で、他の人が言っていたIEEEのものと互換性が保たれます。

>>> sign = functools.partial(math.copysign, 1) # either of these
>>> sign = lambda x: math.copysign(1, x) # two will work
>>> sign(-4)
-1.0
>>> sign(3)
1.0
>>> sign(0)
1.0
>>> sign(-0.0)
-1.0
>>> sign(float('nan'))
-1.0

次に、通常、何かの符号が欲しいときは、結局、別の値を掛けるだけです。 そしてもちろん、それは基本的に copysign が行います。

だから、その代わりに

s = sign(a)
b = b * s

すればいいんです。

b = copysign(b, a)

そうそう、7年間もPythonを使いながら cmp は、そう簡単に削除して sign ! を使ったクラスを実装したことはありませんか? __cmp__ メソッドを使用できますか? を呼び出したことはありませんか? cmp と、カスタムのコンパレータ関数を指定したのでしょうか?

まとめると、自分が欲しくなったのは sign 関数もありますが copysign のように、第一引数を1にしても問題なく動作します。 私は sign よりも有用である。 copysign は、同じ機能の単なるサブセットであることを示しました。