2011-07-05 10 views
1

私はPythonライブラリ用のAPIを設計しており、私の想像力がPythonのかなりの能力を追い越したと思われる状況に遭遇しました。Python API - オプションの括弧を作成するためのパターン?

(私は私のデザインのルビーネスで怒られるかもしれません任意のPythonistasに謝罪したい)

ように基本的には、selfを返し、それぞれがその上にいくつかのメソッドを持つクラスは、そこにあります彼らは一緒に鎖を張ることができます。だから、:

>>> a = MyKlass() 
>>> b = a.method_one() 
>>> c = b.method_two() 

は、私の質問は、カッコはオプションにすることが可能であるかどうかである

>>> a = MyKlass() 
>>> c = a.method_one().method_two() 

と同じになります。私は__getattr____call__を使用して呼び出し可能なオブジェクトを操作する方法について少しは学んだが、これを完全に実装することはできませんでした。今、クラスの__getattr__で属性をチェックしてから、nameがメソッドか属性(またはより正確には呼び出し可能かどうか)を判断します。

>>> class MyKlass(object): 
>>>  def __getattr__(self, name): 
>>>   # pseudocode, you get the idea... 
>>>   if name is callable: 
>>>    def callme(*args, **kwds): 
>>>     # do stuff 
>>>    return callme 
>>>   else: 
>>>    # just return the attribute 

だから、呼び出し可能オブジェクトを返します。

私の問題は、それが呼び出し可能であるならば、私はこのような何かを__getattr__が必要だということです。これを行うには、私が考え

>>> a = MyKlass() 
>>> c = a.method_one.method_two # AttributeError, since a bound function object does not have attribute "method_two" 

唯一の方法は、「できるようにするには、次のようになります。これは、呼び出し可能オブジェクトが返されますが、呼び出されることはありませんされるので、私は、カッコはオプションにすることができなかったこと、しかし、意味しますコード内で先読みして、nameにかっこが付いているかどうかを判断します。次に、nameが呼び出し可能であっても呼び出されなかった場合、呼び出し可能オブジェクトを返す代わりに、引数なしでnameを呼び出した結果を返すことができました。

これはおそらく実行できないと思っていますが、とにかく私は指導者に尋ねると思っていました。

+3

プロパティでない場合は、暗黙的に呼び出されるべきではありません。それは絶対にしないでください。特に図書館で。 PythonはRubyではありません。 –

+0

はい...それは有用ではなく、あなたの図書館を使用する人に多大な混乱を招くかもしれません。 – Ant

+0

私は皆さんの大声ではっきりと聞きました。私は受け入れられた答えとして@ FogleBirdの答えをマークしていますが、私は皆さんがまっすぐで狭いところに私を置くことに感謝します。 –

答えて

4

私はあなたがこれをしたいと思っています。どのような理由がありますか?引数を取るメソッドはどうでしょうか? (下の例を参照してください)

__getattr__の代わりに__getattribute__を使用すると、引数のないメソッドでうまくいくようです。

の作業例:

class Test(object): 
    def __getattribute__(self, name): 
     attr = super(Test, self).__getattribute__(name) 
     if callable(attr): 
      return attr() 
     return attr 
    def f(self): 
     print 'f' 
     return self 
    def g(self): 
     print 'g' 
     return self 
    def h(self, x): 
     print x 
     return self 

t = Test() 
t.f.g # Works fine 
t.f().g # Fails - the parens aren't optional, they must be left off now 
t.f.g.h(1) # Fails - unable to provide an argument 

は、引数の問題を回避するには、機能を検査し、それが(自分以外の)任意の引数を取らない場合にのみ、それを呼び出すことができます。参照:http://docs.python.org/library/inspect.html

自分でこの道をやめてください。

+0

私がしようとしているのは、引数を渡す必要がない場合は括弧がオプションで、引数を渡す必要がある場合は括弧が必要であるということです。したがって、a.method_one(name = 'blah')。method_twoは実際にはa.method_one(name = 'blah')を呼び出すのに対し、 'a.method_one.method_two'は実際には' a.method_one()。method_two() ).method_two() ' –

3

括弧を付けないと、その関数の参照結果が表示されます。これはPythonの構文の基本的な部分です(この一貫性は良いことです!)。

Pythonのproperty関数(または関連するデコレータ)を使用して、メソッドを必要なものを実現するプロパティのエイリアスとしてフード内で動作させることができます。しかし、これはあなたが悪い考えである非常に副作用の強いコードを書いていることを示唆しています。

jQueryの唯一の目的はDOMに副作用を引き起こすことであるため、このような連鎖はjQueryで一般的です。通常、これはアプリケーションのデバッグとテストを非常に困難にするため、他の場所では賢明ではありません。

関連する問題