15

次のコード例(python 2.7)について考えてみます。

class Parent:
    def __init__(self, child):
        self.child = child

    def __getattr__(self, attr):
        print("Calling __getattr__: "+attr)
        if hasattr(self.child, attr):
            return getattr(self.child, attr)
        else:
            raise AttributeError(attr)

class Child:
    def make_statement(self, age=10):
        print("I am an instance of Child with age "+str(age))

kid = Child()
person = Parent(kid)

kid.make_statement(5)
person.make_statement(20)

関数呼び出しがperson.make_statement(20)Child.make_statement関数を介して関数を呼び出すことを示すことができます。関数では、子インスタンスの対応する関数が呼び出される前に、属性を出力できます。これまでのところ明確です。Parent__getattr____getattr__

しかし、呼び出しの引数はどのようにperson.make_statement(20)渡され__getattr__ますか?関数で数値「20」を出力するにはどうすればよいです__getattr__か?

4

1 に答える 1

27

20関数に印刷していません__getattr__。この関数は、Childインスタンスのmake_statement 属性を見つけて、それを返します。たまたま、その属性はメソッドなので、呼び出すことができます。したがって、Pythonは返されたメソッドを呼び出し、そのメソッドはを出力し20ます。

通話を削除して()も、引き続き機能します。メソッドを保存し、個別に呼び出して20印刷することができます。

>>> person.make_statement
Calling __getattr__: make_statement
<bound method Child.make_statement of <__main__.Child instance at 0x10db5ed88>>
>>> ms = person.make_statement
Calling __getattr__: make_statement
>>> ms()
I am an instance of Child with age 10

引数を確認する必要がある場合は、代わりにラッパー関数を返す必要があります。

def __getattr__(self, attr):
    print("Calling __getattr__: "+attr)
    if hasattr(self.child, attr):
        def wrapper(*args, **kw):
            print('called with %r and %r' % (args, kw))
            return getattr(self.child, attr)(*args, **kw)
        return wrapper
    raise AttributeError(attr)

これにより、次のようになります。

>>> person.make_statement(20)
Calling __getattr__: make_statement
called with (20,) and {}
I am an instance of Child with age 20
于 2012-12-08T10:15:55.487 に答える