6

必要なタイプに応じて、呼び出す別のプログラムに対して異なる出力文字列を生成する必要がある関数があります。

基本的に、呼び出されたプログラムには、呼び出されたタイプを示すコマンドライン引数が必要です。

幸いなことに、変数のタイプをチェックする方法について、SOでこの回答を見つけました。しかし、タイプのチェックが「オブジェクト指向ではない」設計を裏切るという、人々がどのように異議を唱えているかに気づきました。それで、タイプを明示的にチェックせずにこれを処理する他の方法、おそらくより「オブジェクト指向」の方法はありますか?

私が今持っているコードは次のようになります:

def myfunc(val):
    cmd_type = 'i'
    if instance(val, str):
        cmd_type = 's'

    cmdline = 'magicprogram ' + cmd_type + ' ' + val
    Popen(cmdline, ... blah blah)
    ...

これは問題なく動作しますが、私が知らないテクニックがあるかどうかを知りたかっただけです。

4

4 に答える 4

5

ダブルディスパッチまたはマルチメソッドを使用できます。

于 2010-10-29T13:10:04.477 に答える
3

Double DispatchingMultimethodsが特に関連しているとは思いませんし、他の SO の回答に対する人々の異議とはあまり関係がないと思います。

驚くことではありませんが、あなたが行っていることをよりオブジェクト指向にするためには、それにいくつかのオブジェクト (および対応するクラス) を導入する必要があります。各値をクラスのインスタンスにすることで、その型のチェックをやめることができます (事実上強制されます)。以下のサンプル コードへの変更は、これを行うための非常に簡単な方法を示しています。

class Value(object):
    """ Generic container of values. """
    def __init__(self, type_, val):
        self.type = type_   # using 'type_' to avoid hiding built-in
        self.val = val

def myfunc(val):
    # Look ma, no type-checking!
    cmdline = 'magicprogram {obj.type} {obj.val}'.format(obj=val)
    print 'Popen({!r}, ... blah blah)'.format(cmdline)
    # ...

val1 = Value('i', 42)
val2 = Value('s', 'foobar')

myfunc(val1)  # Popen('magicprogram i 42', ... blah blah)
myfunc(val2)  # Popen('magicprogram s foobar', ... blah blah)

クラス内にその属性に間接的にアクセスするメソッドがあれば、さらにオブジェクト指向になりますがValue、上記を実行するだけで悪名高い型チェックが不要になります。よりオブジェクト指向の設計では、種類ごとに異なるサブクラスがValueあり、すべてのクライアントが のような共通のメソッド セットを共有して、クライアントmyfunc()から情報を作成、操作、および抽出するために使用します。

myfunc()オブジェクトを使用するもう 1 つの利点は、新しいタイプの 'Value` のサポートをアプリケーションに追加する場合に変更する必要がないことです。「値」の本質の抽象化が優れている場合は、は。

于 2010-10-29T20:46:01.517 に答える
3
    But I noticed how people also raised objections, 
that checking for types betrays a "not object oriented" design

実はダックタイピングスタイル(「アヒルのように見えてアヒルのように鳴くなら、それはアヒルに違いない」)と呼ばれ、このスタイルのプログラミングを推奨しているのがpython言語です。

ダックタイピングでは、EAFP (許可よりも許しを求める方が簡単)と呼ばれるものが登場します。

    presumable more "more object oriented" way of handling this without 
   explicitly checking for type?

あなたはよりpythonicを意味します、基本的にあなたのケースでよりpythonicになるものは次のようなものです:

def myfunc(val):
    cmd_type = 'i'

    # forget about passing type to your magicprogram
    cmdline = 'magicprogram  %s ' % val 
    Popen(cmdline, ... blah blah)

そしてあなたのマジックプログラムで(それがあなたのスクリプトなのかどうかはわかりません...)、そしてすべての場合にあなたのプログラムは文字列を取得するので、スクリプトが受け入れるものに変換してみてください。

from optparse import OptionParser

# ....

if __name__ == '__main__':

    parser = OptionParser(usage="blah blah")

    # ...
    (options, args) = parser.parse_args()

    # Here you apply the EAFP with all type accepted.
    try:
        # call the function that will deal with if arg is string
        # remember duck typing.
    except ... :
        # You can continue here

すべてのコードが何であるかはわかりませんが、上記の例に従うと、よりPythonicになり、すべてのルールに例外があることを覚えているので、おそらくあなたのケースは例外であり、型チェックを行う方がよいでしょう.

これで問題が解決することを願っています。

于 2010-10-29T13:35:31.227 に答える
1

これは、1 つの小さな機能を設計する方法というよりも、大きな問題のエンジニアリングです。それにはさまざまな方法がありますが、多かれ少なかれ同じ一般的な思考プロセスに分解されます。val のタイプがわかっている場合は、それをコマンド ライン引数に変換する方法を指定する必要があります。私だったら、正しいことを行う To Command Line 関数を持つクラスを val にするでしょう。型固有の myfunc 関数を変数に割り当て、必要なときにそれを呼び出すこともできます。

編集:最後のバージョンを次の行に沿って説明するには

Val = "a string"
myfunc = myfuncStringVersion

クラスでvalをラップしたくない場合があるため、クラスでvalをラップする場合とほぼ同じことを行うだけで、値と関数に分割されます。

于 2010-10-29T13:31:56.990 に答える