web-dev-qa-db-ja.com

Python-クラス属性としての関数はバインドされたメソッドになります

そのクラスのインスタンスを作成するときに関数と等しいクラス属性を定義すると、その属性がバインドされたメソッドになることに気付きました。誰かが私にこの行動の理由を説明できますか?

In [9]: def func():
   ...:     pass
   ...: 

In [10]: class A(object):
   ....:     f = func
   ....:     

In [11]: a = A()

In [12]: a.f
Out[12]: <bound method A.func of <__main__.A object at 0x104add190>>

In [13]: a.f()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-13-19134f1ad9a8> in <module>()
----> 1 a.f()
    global a.f = <bound method A.func of <__main__.A object at 0x104add190>>

TypeError: func() takes no arguments (1 given)
15
se7entyse7en

関数を属性fに割り当てました。関数がクラス内にあるため、メソッド、具体的にはバインドされたメソッドになります(オブジェクトにバインドされているため、 詳細はこちら )。

クラス内のメソッドは、特に指示されていない限り、少なくとも1つのパラメーター(self)を受け取ります クラスメソッドと静的メソッド -を参照してください。このため、エラーはfuncは引数を取りません(def func():として定義されているため)が、1を受け取りました(self

あなたがやりたいことをするために、あなたはpythonあなたが 静的メソッド を使用していることを伝えるべきです

def func():
    pass

class A(object):
    f = staticmethod(func)
11
Mr. E

PythonはnotメッセージベースOO system1。代わりに、JavaScriptと同様に、プロパティはファーストクラス関数に解決されてから呼び出されます。発見されたように、動作はそのようなメカニズムで少し異なります。

Pythonの要件は、メソッドに少なくとも1つのパラメーター(通常はselfと呼ばれる)があり、関連付けられたインスタンスが自動的に提供されることですいつ呼び出されます方法として。

さらに(そしておそらく質問のポイントまで)、Pythonは、インスタンスメンバーのバインディングを確立するときに_def f.._とf = some_func()のどちらを使用するかを区別しません。おそらくこれは動作と一致します。クラスの外。

この例では、関数をインスタンスに割り当てると、インスタンスメソッドのように扱われることが期待されます。これは、どちらの場合も呼び出されるまったく同じ(パラメーターなし)関数です。そのようなものの将来の使用法のみが関係します。

現在、JavaScriptとは異なり、Pythonは、バインドされたメソッドの概念を通じてメソッドとオブジェクトの関連付けを処理します。メソッドとして解決される関数は常に「バインド」されます。

バインドされたメソッド(バインドされたオブジェクトをselfとして最初のパラメーターに自動的に提供する関数)を返す_a.f_の動作は、関数のソースとは無関係に実行されます。この場合、これは、selfパラメーターを受け入れないため、パラメーターなしの関数が「バインド」されている場合は使用できないことを意味します。

デモンストレーションとして、ソースの基になるメソッドがnotインスタンスを引数として受け入れるための最小要件を満たしているため、以下は同じ方法で失敗します。

_g = a.f
g()
_

この場合、g()を呼び出すことはfunc(a)を呼び出すことと同じです。


1 比較のために、Java、C#、Ruby、およびSmalltalkはメッセージベースですOOシステム-これらでは、オブジェクトは、メソッド(または関数)を解決する代わりに、「名前」でメソッドを呼び出すように指示されます)呼び出すことができる値として。

1
user2864740