取り込まれたパラメーターのタイプに応じて異なる動作をする必要がある関数があります。私の最初の衝動は、isinstance への呼び出しをいくつか含めることでしたが、スタックオーバーフローで、これは悪い形式であり、pythonic ではないという回答が見られますが、その理由はあまりありません。その悪い形と非pythonic。後者については、ダックタイピングと関係があると思いますが、引数が特定の型であるかどうかを確認するのはどうですか? 安全にプレイしたほうがいいのではないですか?
4 に答える
この素晴らしい投稿を参照してください
この問題に関する私の意見は次のとおりです。
- コードを制限している場合は、それを行わないでください。
- コードを指示するために使用している場合は、非常に特定のケースに限定してください。
良い例: (これで問題ありません)
def write_to_file(var, content, close=True):
if isinstance(var, str):
var = open(var, 'w')
var.write(content)
if close:
var.close()
悪い例: (これは悪い)
def write_to_file(var, content, close=True):
if not isinstance(var, file):
raise Exception('expected a file')
var.write(content)
if close:
var.close()
そうすることで、ダックタイピングが明示的に防止されるためです。
これが例です。このcsv
モジュールを使用すると、データを CSV 形式でファイルに書き込むことができます。そのため、関数はファイルをパラメーターとして受け入れます。しかし、実際のファイルではなく、オブジェクトのようなものに書き込みたい場合はどうすればよいStringIO
でしょうか? StringIO
必要な読み取りおよび書き込みメソッドを実装しているため、これは完全に適切な使用方法です。しかしcsv
、 type の実際のオブジェクトを明示的にチェックしていた場合file
、それは禁止されます。
一般に、Python は可能な限り多くのことを許可する必要があるという見解をとっています。これは、クラスに実際のプライベート変数がないことの背後にある理由と同じです。
isinstance を使用すると、ポリモーフィック ディスパッチが再実装されることがあります。を見て、それぞれの型で個別に実装されているものをstr(...)
呼び出します。object.__str__(..)
実装することで、組み込みのメソッドを操作する代わりに、その 1 つのオブジェクトを拡張する__str__
ことで依存するコードを再利用できます。str
str(...)
基本的に、これが OOP の頂点です。ポリモーフィックな動作が必要で、タイプを綴りたくありません。
ただし、それを使用する正当な理由があります。
を使用isinstance
すると、関数に渡すことができるオブジェクトが制限されます。例えば:
def add(a,b):
if isinstance(a,int) and isinstance(b,int):
return a + b
else:
raise ValueError
今、あなたはそれを呼び出すことを試みるかもしれません:
add(1.0,2)
得られることを期待していますが、整数ではない3
ため、代わりにエラーが発生します。1.0
明らかに、isinstance
ここで使用すると、関数が本来の有用性を発揮できなくなります。最終的に、オブジェクトをローストしたときにアヒルのような味がする場合、それらが機能する限り、オブジェクトがどのタイプで開始されたかは気にしません。
ただし、逆の場合もあります。
def read(f):
if isinstance(f,basestring):
with open(f) as fin
return fin.read()
else:
return f.read()
要点は、関数に持たせたい API を決定する必要があるということです。関数がタイプに基づいて異なる動作をする必要があるケースは存在しますが、まれです (ファイルを開くために文字列をチェックすることは、私が知っているより一般的な用途の 1 つです)。