5

Python では、実行時にメソッドをクラスに追加できることを知っています。

class Test:
    def __init__(self):
        self.a=5

test=Test()

import types
def foo(self):
    print self.a
test.foo = types.MethodType(foo, test)
test.foo() #prints 5

また、クラス定義でデフォルトのsetattrをオーバーライドできることも知っています。

class Test:
    def __init__(self):
        self.a=5
    def __setattr__(self,name,value):
        print "Possibility disabled for the sake of this test"

test=Test() #prints the message from the custom method called inside __init__

ただし、実行時にsetattrをオーバーライドすることはできないようです:

class Test:
    def __init__(self):
        self.a=5

test=Test()

import types
def __setattr__(self,name,value):
    print "Possibility disabled for the sake of this test"
test.__setattr__ = types.MethodType(__setattr__, test)
test.a=10 #does the assignment instead of calling the custom method

最後の 2 つのケースでは、dir(test) はメソッドsetattrも報告します。ただし、最初のケースでは正しく動作しますが、2 番目のケースでは正しく動作しません。明示的に呼び出すこともでき、その場合は機能することに注意してください。メソッドが定義されている間、デフォルトの代入メソッドをオーバーライドするために正しくマッピングされていないようです。何か不足していますか?

ちなみにPython2.7を使っています。プログラム設計の観点からそのようなことを行うのはおそらく良い考えではないため、質問はほとんど学術的なものですが、それでも回答に値します-検索しても、どこにも文書化されていませんでした.

4

2 に答える 2

3

これは、データ モデルの「クラス インスタンス」セクションに記載されています。

属性の割り当てと削除は、クラスの辞書ではなく、インスタンスの辞書を更新します。クラス__setattr__()or __delattr__()メソッドがある場合、インスタンス ディクショナリを直接更新する代わりに、これが呼び出されます。

したがって、古いスタイルか新しいスタイルかに関係なく、これら 2 つのチェックは常にインスタンスではなく型に対して行われます。

于 2012-11-16T00:24:04.147 に答える
2

Python ドキュメントのこのセクションを参照してください: new-style クラスの特別なメソッド検索

新しいスタイルのクラスの場合、特別なメソッドの暗黙的な呼び出しは、オブジェクトのインスタンス ディクショナリではなく、オブジェクトの type で定義されている場合にのみ正しく動作することが保証されます。

この背後にある理論的根拠の詳細については、リンクをたどってください。私が理解している基本的な考え方は、インスタンス オブジェクトと型オブジェクト ( など__repr__) の両方に適用される特別なメソッドを一貫して呼び出す必要があるということです。常にオブジェクトの型でメソッドを呼び出すことにより、明示的な引数を常に渡すことがわかっていますが、インスタンス ディクショナリがバイパスされるという副作用があります。

于 2012-11-16T00:12:45.613 に答える