2009-09-18 7 views
8

generic functionは、すべての引数の型に基づいて送出されます。プログラマは関数のいくつかの実装を定義します。正しい引数は、引数の型に基づいて呼び出し時に選択されます。これは他のものの中でオブジェクトの適応に役立ちます。 Pythonには、len()などのいくつかの汎用関数があります。Python用に最もよく管理されている汎用関数の実装は何ですか?

これらのパッケージは、このようなコードを許可する傾向がある:

@when(int) 
def dumbexample(a): 
    return a * 2 

@when(list) 
def dumbexample(a): 
    return [("%s" % i) for i in a] 

dumbexample(1) # calls first implementation 
dumbexample([1,2,3]) # calls second implementation 

私は、ユーザーが必要とするWebコンポーネントになり、最近について考えてきた小さいダム例。

class WebComponentUserAdapter(object): 
    def __init__(self, guest): 
     self.guest = guest 
    def canDoSomething(self): 
     return guest.member_of("something_group") 

@when(my.webframework.User) 
componentNeedsAUser(user): 
    return WebComponentUserAdapter(user) 

Pythonはいくつかの一般的な機能の実装があります。代わりに、特定のWebフレームワークを必要とする、積分器はただのようなものを書く必要があるでしょう。なぜ私は他の人よりも1つを選ぶだろうか?その実装はどのようにアプリケーションで使用されていますか?

私はZopeのzope.component.queryAdapter(object, ISomething)に精通しています。プログラマは、引数として特定のクラスのオブジェクトをとり、インタフェースと互換性のあるものを返す呼び出し可能なアダプタを登録します。これはプラグインを許可する便利な方法です。サルパッチとは異なり、オブジェクトが同じメソッド名を持つ複数のインタフェースに適応する必要がある場合でも機能します。

+1

'len'関数は単にオブジェクトの' __len__'メソッドを呼び出します。これは「汎用」機能の意味ですか?そうであれば、このようにふるまう機能は比較的少ない。他に何か覚えていますか?もしそうなら、より良い例を選んでください。 –

+0

多形性について話していますか?または、多型を追加するために既存のタイプを猿でパッチすることについて話していますか? –

+0

joeforkerはオーバーロードされた関数を実装しようとしています(?およびウィキペディアのリンクに基づいています)。 私は、関数が1つの名前で呼び出されますが、渡されたパラメータに基づいて異なるコードを実行するという意味で、彼は「汎用」を参照していると思います。 したがって: はmy_function(A) - > function_a はmy_functionを実行する(B) - > function_b を実行することが – Mark

答えて

7

P. EbyがPEAK-Rulesライブラリをお勧めします。同じ著者(ただし、非推奨)はRuleDispatchパッケージ(PEAK-Rulesの前身)です。後者はもはやIIRCを維持していない。

PEAK-Rulesにはすばらしい機能がたくさんありますが、それは拡張性がありません。タイプ上の "クラシック"ディスパッチのほかに、それは "ガーディアン"としての任意の表現のディスパッチを特徴とする。

単にそのままlen()機能は、真の汎用関数(少なくとも意味でも、上述した、およびパッケージの意味において、この用語はCommon LispDylan又は​​などの言語で使用されている)ではありません便利特別という名前の呼び出しのためのシンタックス(それ以外レギュラー)方法:

len(s) == s.__len__() 

また、これは単一のディスパッチであることが、注意は、すなわち、実際の受信機(上記のコードでs)はメソッドの実装を決定しますと呼ばれる。また、仮説でさえも、呼び出されるメソッドが解決されたときに受信側のみが使用されるため、依然として仮想的なものでもあります。残りの引数は単に渡されますが、メソッドの選択には影響しません。

これは、専用の受信者が存在しないマルチディスパッチとは異なり、呼び出す実際のメソッド実装を見つけるためにすべての引数が使用されます。これは、実際にはすべてを価値あるものにするものです。それが構文的な砂糖のほんの奇妙な種類のものであれば、誰もそれを使用することを悩ますことはありません、IMHO。この例では

from peak.rules import abstract, when 

@abstract 
def serialize_object(object, target): 
    pass 

@when(serialize_object, (MyStuff, BinaryStream)) 
def serialize_object(object, target): 
    target.writeUInt32(object.identifier) 
    target.writeString(object.payload) 

@when(serialize_object, (MyStuff, XMLStream)) 
def serialize_object(object, target): 
    target.openElement("my-stuff") 
    target.writeAttribute("id", str(object.identifier)) 
    target.writeText(object.payload) 
    target.closeElement() 

serialize_object(MyStuff(10, "hello world"), XMLStream()) 

のような呼び出しが実際に呼び出されなければならない方法を決定するために両方の引数を考慮します。

Pythonの汎用関数を使い分けるのは、peak.securityのリファクタリングされたコードを読んで、汎用関数(RuleDispatchを使用)を使って権限チェックにアクセスする非常に洗練されたソリューションです。

+0

何のhttpについてを実行するコードを取得する** kwargsからの構文解析よりスタイリッシュな実装です://は、PyPI .python.org/pypi/simplegenericもPJEのですか? – joeforker

+0

AFAIKこれは非常に単純な実装であり、タイプベースのディスパッチのみを行います。私はそれを実際に見ていないので、私はそれについて何も言えません。私の経験は主に 'RuleDispatch'とその後継者です。 – Dirk

+1

シンプルなジェネリックは単純ですが、もっと複雑で豊かなピークほど積極的に維持されているわけではありません。 –

0

次のような建設使うことができます。引数は、任意の名前なし引数のリストになり、kwargsからは名前のものの辞書になります。この場合、

def my_func(*args, **kwargs): 
    pass 

を。ここからあなたのタイプを検出し、適切な動作をすることができます。

+1

これは、修正された質問の文脈では意味をなさない。 –

+0

ええ、当時は正解のようでした。 – defrex

0

これらの「一般的な」機能のポイントを見ることができません。単純な多形性のように聞こえる。

「ジェネリック」機能は、ランタイムタイプの識別に頼ることなく、このように実装できます。

class intWithDumbExample(int): 
    def dumbexample(self): 
     return self*2 

class listWithDumbExmaple(list): 
    def dumpexample(self): 
     return [("%s" % i) for i in self] 

def dumbexample(a): 
    return a.dumbexample() 
+1

あなたのアプローチでは、OPの仕様(およびすべての汎用関数パッケージで許される)に従って 'dumbexample(1) 'を呼び出すことはできません。通常、タイプ(eep)に基づいて切り替えることで、それぞれの呼び出しに対して煩わしいラッピングが必要です。しかし、古典的なOOPが完全に崩壊し、Common Lisp、Dylanなどのような汎用関数が本当に光っているのは、複数の引数の型に基づいてディスパッチすることです(Visitor、__radd__などのようなklutzを避ける) vs __add__、その他数多くのOOPが必要です)。 –

+0

@Alex Martelli:おそらく、強制的な問題や二重の派遣の問題を避ける。 OPの質問(例)は、これに触れていませんでした。私は* real *の質問についてまだ不明です。あるいは、おそらく疑問はちょうど仮説的なものでした。 –

関連する問題