2012-11-24 1 views
6

メソッドをあるクラスから別のクラスにコピーするにはどうしたらいいですか?pythonメソッドstealer

例コード:

class A(object): 
    def foo(self): 
    print "blah" 


class B(object): 
    foo = A.foo 

B().foo() 

予想される出力:代わりに

"blah" 

TypeError: unbound method foo() must be called with A instance as first argument (got nothing instead)

+1

'foo'がインスタンスメソッドではなくクラスメソッドであった場合、これは意味をなさないでしょう。 – NullUserException

答えて

6

使用__func__

the docsを引用
>>> A.foo 
<unbound method A.foo> 
>>> A.foo.__func__ 
<function foo at 0x00BC5F70> 
>>> class B(object): 
... foo = A.foo.__func__ 
... 
>>> B().foo() 
"blah" 

An instance method object combines a class, a class instance and any callable object (normally a user-defined function).

Special read-only attributes: __self__ is the class instance object, __func__ is the function object; __doc__ is the method’s documentation (same as __func__.__doc__); __name__ is the method name (same as __func__.__name__); __module__ is the name of the module the method was defined in, or None if unavailable.

+0

また、「A.foo .__ func__」の代わりに 'A()。foo'を実行することもできます。 – jdotjdot

+2

@jdotjdot 'A()。foo'は、その特定のインスタンス「A」に結びついた「束縛メソッド」です。これは、(おそらく単純化された)例では重要ではありません。なぜなら、 'self'を使わず、静的/クラスメソッドに置き換えることができるからです。しかしもっと複雑なシナリオではそうです。私は、OPの意図は無論ではあるが、任意のクラスから有用なメソッドを選ぶことであると仮定している(つまり、ミックスインではなく継承されることを意図していない)彼のクラスのインスタンスに作用し、元のものではない。 – mgibsonbr

+0

あなたは正しいです。私はこの特定の例では、 'self'は必要ではないので、考えていましたが、一般化されたケースでは' A().foo'は良い呼び出しではありません。 – jdotjdot

1

あなたがここにclass inheritanceを使用することができます。継承を使用すると、別のオブジェクトに基づいてオブジェクトを作成し、そのすべての関数と属性を継承できます。この場合

が、それは次のようになります。その宣言後

class A(object): 
    def foo(self): 
    print "blah" 


class B(A): 
    # You can add new methods or attributes here, 
    # or even overwrite those inherited from A if you 
    # really want to, though you have to be careful with that. 
    pass 

>>> B().foo() 
"blah" 

。これは動作します。それのためにあなたはクラスA作成

  • 、および作成方法foo
  • あなたはAは、「それを出産した、」いつBAが持っているすべてのものを持って生まれたことを意味し、Aからを継承するクラスBを作成しました。
    • 私たちの場合、BAの正確なコピーです。それ以外は何もしませんでした。しかし、私たちは変更を加えたり、メソッドを追加することができます。

例:使用中、我々は参照してくださいね

class A(object): 
    def foo(self): 
     print "blah" 

class B(A): 
    def newfoo(self): 
     print "class A can't do this!" 

:特に

>>> A().foo() 
blah 
>>> B().foo() 
blah 
>>> A().newfoo() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
AttributeError: 'A' object has no attribute 'newfoo' 
>>> B().newfoo() 
class A can't do this! 

、あなたのコードは、上記機能しなかった理由ということですがB.fooを設定しようとすると、書きました

class B(object): 
    foo = A.foo 

代わりの

class B(object): 
    foo = A().foo 

あなたは()なしA.fooを書いたとき、あなたはまっすぐPythonで動作しないでしょうAタイプ、から方法を求めました。 foo = A().fooを実行する場合は、Aオブジェクトをインスタンス化し、そのメソッドfooのコピーを取得してから割り当てます。

2

ここでの問題は、それはあなたが盗むしようとしているバインドされた方法であるということです、しかし、あなたの例では、その機能を必要としませんインスタンス状態(self)を使用します。

  1. A.fooの定義を作成し、静的メソッド(@staticmethodデコレータ)
  2. 飾るまたは未使用の引数を渡す機能をラップ:したがって、次の2つの即時のオプションがあります。例えば。 functoolsを使用してください。

例:

import functools 
stolen = functools.partial(A.foo, None) 

これは、あなたのメソッドは、インスタンスの状態を使用しないために動作し、サブクラスを作成する必要はありません。

バインドされたインスタンスメソッド(A.fooなど)には、バインドされたインスタンス引数(self、selfはAのインスタンス)が必要です。通常の使用では、この最初の引数は自動的に渡されます。今すぐ

a = A() 

a.foo() 
A.foo(a) 

...両方等価です。最初のケースでは、構文instance.bound_method()は、字句的な観点からInstanceClass.bound_method(instance)instanceselfに解決されます)を表しています。このため、Aのインスタンスが必要であるため、A.foo()を呼び出すとエラーが発生します。

上記の解決策は、Noneをインスタンスとして渡す関数に関数をワープすることです。インスタンスは決して使用されないため(状態ベースのロジックはありません)。 staticメソッドを使用する場合は、第1の暗黙の期待バインドインスタンス引数selfを削除します。