Python に sign 関数がないのはなぜですか? 質問する

Python に sign 関数がないのはなぜですか? 質問する

Python に 関数がないのはなぜか理解できません。組み込み関数 (の姉妹版だと考えています)signはありますが、 はありません。abssignsign

Python 2.6では、関数copysign数学) がありますが、符号はありません。 を書いてから直接を取得できるcopysign(x,y)のに、なぜ をわざわざ書くのでしょうか。後者の方がはるかに明確です。つまり、x に y の符号が付きますが、copysign では、x に y の符号があるのか​​、y に x の符号があるのか​​を覚えておく必要があります。signcopysignabs(x) * sign(y)

明らかに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

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

編集 - Peter Hansen のコメントを受けて。使用しなかったのは結構ですが、Python を何に使用したかは述べていません。Python を使い始めて 7 年になりますが、数え切れないほど必要になりました。最後の手段が、ついに我慢の限界に達しました。

はい、 cmp を渡すことはできますが、それを渡す必要があった場合の 90% は、lambda x,y: cmp(score(x),score(y))sign でも問題なく機能するような慣用句でした。

sign最後に、 はよりも便利だということに同意していただければ幸いですcopysign。ですから、たとえあなたの意見に賛成したとしても、 sign ではなく を数学で定義することにこだわる必要があるでしょうか? copysign が sign よりもどうしてそんなに便利なのでしょうか?

ベストアンサー1

編集:

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

そこで彼らは、(より冗長ではあるが)コピーサインのみを実装することにした。エッジケースの望ましい動作をエンドユーザーに委任するために使用される- どれの時には電話が必要になるかもしれませんcmp(x,0)


なぜそれが組み込まれていないのかはわかりませんが、いくつか考えがあります。

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

最も重要なのは、copysignが のスーパーセットであるということですsign。x=1 で呼び出すのは関数copysignと同じです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)

そうですね、Python を 7 年間使用していて、 をcmp簡単に削除して に置き換えることができると考えるとは驚きですsign。 メソッドを使用してクラスを実装したことがありませんか?カスタム比較関数を__cmp__呼び出して指定したことがありませんか?cmp

要約すると、私も関数が欲しいと思いましたsignが、最初の引数が 1 であれば問題なく動作します。 は単に同じ機能のサブセットに過ぎないことを示したので、よりも の方が便利であるという意見にはcopysign同意できません。signcopysign

おすすめ記事