31

簡単な例を見てください。

class A:
  def __init__(self, flag):
    self.flag = flag

  def func(self):
    print self.flag

a = A(1)
b = A(2)
callback_a = a.func
callback_b = b.func

callback_a()
callback_b()

結果は次のとおりです。

1
2

期待どおりに動作します。しかし、私は質問があります。Cでは、コールバック関数がポインターとして渡されます。Pythonでは、これを行うための同様の方法が必要であるため、呼び出し元は関数のアドレスを知っています。しかし、私の例では、同じクラスの同じメソッドが異なる結果を出力するため、関数ポインターだけでなく、パラメーター(self)も渡されます。だから私の質問は:

  1. Pythonのそのようなメソッドは、メモリに1つのコピーしかありませんか?私の意味は、どのメソッドのコードにもコピーが1つしかないということです。私の例では、メソッド自体は複製されません。コピーは1つだけでよいと思いますが、ここでは、より多くの入力を取得するために、この質問をします。

  2. Pythonのすべてがオブジェクトであることを覚えています。したがって、私の例では、パラメーターが異なる2つの関数インスタンスがありますが、コードのコピーは1つだけですか?

4

2 に答える 2

24

Pythonでは、コールバックは単なるメンバー関数への参照ではありません。代わりに、作成時に参照するオブジェクトに「バインド」されます。したがってa.func、にバインドされた呼び出し可能オブジェクトを作成しa、にバインドされb.funcた呼び出し可能オブジェクトを作成しbます。

Pythonfunc()はメモリ内に1つの実装のみを必要としますが、バインディングを実行するために実行時に1つ以上の「トランポリン」関数を作成する可能性があります(これに関する内部の詳細はわかりません。とにかくPythonの実装間で異なります)。

印刷するid(callback_a)id(callback_b)異なる結果が得られ、それらが実際に異なる呼び出し可能オブジェクトであることが示されます。

于 2012-04-04T01:34:33.413 に答える
23

CPythonに固有で、関数オブジェクトのコピーは1つだけです。インスタンスの作成中に、クラスはバインドされていない関数をバインドされたメソッドとして名前空間にラップします。しかし、それらはすべて同じ関数をラップします。

これが何が起こっているかを示すために拡張された例です。

class A(object):
  def __init__(self, flag):
    self.flag = flag

  def func(self):
    print self.flag

a = A(1)
b = A(2)

callback_a = a.func
callback_b = b.func

print "typeof(callback_a) = {0}".format(type(callback_a))
print "typeof(callback_b) = {0}".format(type(callback_b))

print "typeof(callback_a.__func__) = {0}".format(type(callback_a.__func__))
print "typeof(callback_b.__func__) = {0}".format(type(callback_b.__func__))

print "'callback_a.__func__ is callback_b.__func__'  is {0}".format(callback_a.__func__ is callback_b.__func__)

callback_a()
callback_b()

このコードは出力します

typeof(callback_a) = <type 'instancemethod'>
typeof(callback_b) = <type 'instancemethod'>
typeof(callback_a.__func__) = <type 'function'>
typeof(callback_b.__func__) = <type 'function'>
'callback_a.__func__ is callback_b.__func__'  is True

is演算子を使用すると、両方のinstancemethodクラスが同じ関数オブジェクトを共有していることがはっきりとわかります。

于 2012-04-04T01:42:59.113 に答える