1

私はまだPythonにかなり慣れていないので、動的型付けに慣れようとしています。特定の型のパラメーターを期待する関数またはクラスがありますが、それに対して強制可能な別の型の値を取得できる場合があります。たとえば、が期待しているfloatが、代わりにintまたはdecimalを受け取る場合があります。または、文字列を期待するかもしれませんが、代わりに__str__特別なメソッドを定義するオブジェクトを受け取ります。

引数を正しいタイプ(およびその理由)に強制するためのベストプラクティスは何ですか?関数/クラスまたは呼び出し元でそれを行いますか?発信者の場合、関数でもチェックしますか?例えば。

代替案1:

def myfunc(takes_float):
    myval = float(takes_float)

myfunc(5)

代替案2:

def myfunc(takes_float):
    myval = takes_float

myfunc(float(5))

代替案3:

def myfunc(takes_float):
    assert isinstance(takes_float, float)
    myval = takes_float

myfunc(float(5))

私はすでにこの答えこれを読んでいて、Pythonで型をチェックするのは「悪い」と言っていますが、静的に型付けされたコンパイラによって即座に検出される非常に単純なバグを追跡するのに時間を無駄にしたくありません言語。

4

3 に答える 3

8

あなたがそうすることが不可欠であるとき、そしてそれ以前ではないとき、あなたは「強制」します(おそらく-それはヌープかもしれません)。たとえば、floatを受け取り、その正弦と余弦の合計を返す関数があるとします。

import math
def spc(x):
  math.sin(x) + math.cos(x)

xをどこに「強制」してフロートさせる必要がありますか?回答:どこにもありません-sinとcosはあなたのためにその仕事をします、例えば:

>>> spc(decimal.Decimal('1.9'))
0.62301052082391117

では、 (できるだけ遅く)強制することが不可欠なのはいつですか?たとえば、引数で文字列メソッドを呼び出したい場合は、それが文字列であることを確認する必要があります。たとえば、.lower文字列以外で呼び出そうとすると、機能しlenない可能性がありますが、 argは、たとえばリスト(文字列としての表現が占める文字数ではなく、リスト内のアイテムの数を指定します)などです。

エラーのキャッチに関しては、ユニットテストを考えてください。半ばまともなユニットテストは、静的型付けで発生するすべてのエラーをキャッチし、次にいくつかのエラーをキャッチします。しかし、それは別の主題です。

于 2009-12-16T05:34:12.637 に答える
2

それは本当に依存します。なぜ必要なfloatですか?int機能を壊しますか?もしそうなら、なぜですか?

floatが持つ関数/プロパティをサポートするパラメータが必要な場合は、intその関数/プロパティを確認する必要があります。パラメータがたまたま であるということではありませんfloat。オブジェクトが必要なことを実行できることを確認してください。それがたまたまあなたがよく知っている特定の型であるということではありません。

おそらく、誰かが Python の実装に重大な問題を発見し、ライブラリfloatを作成するでしょう。notbrokenfloatいくつかのエキゾチックなバグを修正しながら float が行うすべてをサポートするかもしれませんが、そのオブジェクトは type ではありませんfloat。手動で にキャストすると、floatこの気の利いた新しいクラスのすべての利点が失われる可能性があります (または完全に壊れる可能性があります)。

はい、それはありそうもない例ですが、動的型付け言語を扱う場合は、これが正しい考え方だと思います。

于 2009-12-16T05:39:27.820 に答える
0

整数と浮動小数点数が問題になるのは1回だけです。これは、奇妙でデバッグが難しい「単純な」バグを見つける唯一の機会です。

分割。

他のすべては、必要なときに必要な変換を行います。

Python 2.xを使用して/いて、何も考えずに演算子をさりげなく投げ回している場合、一般的な状況では、間違ったことをしてしまう可能性があります。

いくつかの選択肢があります。

  1. from __future__ import division除算のためのPython3セマンティクスを提供します。

  2. -Qnew新しい分割セマンティクスを取得するには、常にオプションを指定して実行してください。

  3. floatニア/オペレーションを使用します。

タイプが重要になるのはディビジョンだけです。整数がfloatとは異なる動作をして、結果に静かに影響を与えるのはこのときだけです。

他のすべてのタイプの不一致の問題は、TypeError例外を除いて見事に失敗します。他のすべて。デバッグに時間を無駄にすることはありません。何が悪いのかすぐにわかります。


具体的には。

「文字列を期待しているが文字列を取得できなかった」というデバッグはありません。これは、トレースバックですぐにクラッシュします。混乱はありません。思考を失う時間はありません。関数が文字列を期待する場合、呼び出し元は文字列を提供する必要があります-それがルールです。

上記の代替案2は、文字列を予期する関数があり、混乱して文字列を提供するのを忘れた場合の問題を修正するためにめったに使用されません。この間違いはめったに起こらず、すぐに型例外が発生します。

于 2009-12-16T11:36:19.127 に答える