2010-12-31 9 views
4

私はselfパラメータにいくつかの問題があります。そして、Pythonの一見矛盾した動作が私を迷惑にしています。私はクラス、Fooを持っています。このクラスには、m1からmNまでの一連のメソッドがあります。これらのうちのいくつかについては、下記のm1のような標準的な定義を使用します。しかし、他の人にとっては、私がm2m3で行ったように、メソッド名を直接代入する方が便利です。今Pythonとselfパラメータ

import os 

def myfun(x, y): 
    return x + y 

class Foo(): 
    def m1(self, y, z): 
     return y + z + 42 

    m2 = os.access 
    m3 = myfun 

f = Foo() 
print f.m1(1, 2) 
print f.m2("/", os.R_OK) 
print f.m3(3, 4) 

、私はos.accessselfパラメータ(一見)を取らないことを知っています。そして、このタイプの割り当てにはまだ問題はありません。しかし、私は自分のモジュールで同じことをすることはできません(myfunmymodule.myfunで定義されていると想像してください)。上記のコードを実行すると、次の出力が得られます。

3 
True 
Traceback (most recent call last): 
    File "foo.py", line 16, in <module> 
    print f.m3(3, 4) 
TypeError: myfun() takes exactly 2 arguments (3 given) 

問題が原因私は仕事の枠組みに、私は少なくともクラスFooを避けることができない、ということです。しかし、ダミーのクラスに私のmymoduleのものがあるのを避けたいです。これを行うには、私は何かalaをする必要があります

あなたがそれらのような20を持っている場合、これは非常に冗長です。ですから、どうやってどうやってやっているのでしょうか?それとも、どうやらもっとスマートなやり方で、どうやって自分のモジュールを組み込みのように振る舞うかということです。

答えて

2

私はちょうどルークが暗示したように動作が矛盾していないと付け加えたいと思います。

ちょうどあなたがPythonがM1とM2を区別できないことを見ることができますここで、次の

print Foo.__dict__ 
    {'__doc__': None, 
    '__module__': '__main__', 
    'm1': <function m1 at 0x02861630>, 
    'm2': <built-in function access>, 
    'm3': <function myfun at 0x028616F0>} 

を試してみてください。 そのため、両方がbound-methodで評価されます。

バインドされたメソッドは、オブジェクトを指し示す追加の最初の引数を持つメソッドのようなものです:self.m(1, 2) -> m(self, 1, 2)

この結合挙動のみユーザ定義のメソッドのために実装されています。それはself.m2("/", os.R_OK)m2(self, "/", os.R_OK)に評価されない理由を説明します。

最後に一つデモ:

print Foo.m1 
    <unbound method Foo.m1> 
print Foo.m2 
    <built-in function access> 
print f.m1 
    <bound method Foo.m1 of <__main__.Foo instance at 0x02324418>> 
print f.m2 
    <built-in function access> 

異なる機能タイプの詳細については、ここで見つけることができます:

http://docs.python.org/reference/datamodel.html

そして、この結合メカニズムはまた、使用することによって防止することができる前に述べたように静的メソッド記述子

http://docs.python.org/library/functions.html#staticmethod

0

一つの方法は、手動で静的メソッドのデコレータを適用することであろう。

class Foo(object): 
    m3 = staticmethod(mymodule.myfun) 
4

os.access()クラスが定義されている場合、それはCで書かれた拡張モジュールの一部であるという意味で、組み込み関数でありますPythonはメソッドとしてm2を認識しません。なぜなら、型が間違っているからです。メソッドはPython関数であり、C関数ではありません。しかし、m3はPythonの関数なので、メソッドとして認識され、そのように扱われます。

つまり、それはm2です。これは例外で、m3ではありません。

あなたが欲しいものを行うための一つの簡単な方法は、 m3静的メソッドにするだろう

m3 = staticmethod(myfun) 

を今インタプリタは、それがAのm3方法として呼ばれていたときにselfパラメータを試してみて、myfun()を渡すために決して知りませんFooオブジェクト。

+0

あなたの一般的なポイントは、理にかなって、私はモジュールはC、Pythonの、またはBefunge –

+0

ポイントで書かれているかどうかをどのようにその関連が表示されませんインタプリタに動的にリンクされた*ネイティブコード*として実行されるということです。あなたは正しいのですが、コンパイルされた言語でも構いません。 –

+0

'staticmethod'は、正常に動作します。しかし、組み込みのコードやネイティブコード、あるいはどんなIMOでも、動作が異なるはずはありません。だから、私は作業コードのために解決すると思うし、理解は別の時に来る必要があります。 – Svend

2

私はあなたがstaticmethod()を探していると思います。 docs hereを参照してください。

m2 = staticmethod(os.access) 
m3 = staticmethod(myfun) 

m2があなたの例で働いていて、m3がそうでなかった理由として、それは私には分かりません。元の例のf.m2とf.m3を表示すると、f.m2は組み込み関数os.accessへの直接参照であり、f.m3はバインドされたメソッド(インスタンスfにバインドされている)です。

1

この場合、staticmethod関数を使用する必要があります。静的クラスメソッドを書くとき、あなたはデコレータとしてそれを使用することができます。

class A: 
    def printValue(self,value): 
     print value 

    @staticmethod 
    def staticPrintValue(value): 
     print value 

>>> A.printValue(5) 
Traceback (most recent call last): 
    File "<pyshell#2>", line 1, in <module> 
    A.printValue(5) 
TypeError: unbound method printValue() must be called with A instance as first argument (got int instance instead) 

>>> A.staticPrintValue(5) 
5 
関連する問題