python 如何通过__getattr__将参数传递给函数

bvjxkvbb  于 2022-12-28  发布在  Python
关注(0)|答案(2)|浏览(170)

考虑下面的代码示例(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)通过Parent__getattr__函数调用Child.make_statement函数。在__getattr__函数中,我可以在调用子示例中的相应函数之前打印出属性。到目前为止,一切都很清楚。
但是调用person.make_statement(20)的参数是如何通过__getattr__传递的呢?我如何能够在__getattr__函数中打印出数字'20'呢?

vh0rcniy

vh0rcniy1#

你没有在__getattr__函数中打印20。函数在Child示例上找到make_statementattribute 并返回它。碰巧的是,那个属性是一个方法,所以它是可调用的。Python因此调用返回的方法,然后 that 方法打印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

如果你 * 必须 * 才能看到参数,你就必须返回一个 Package 器函数:

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
eit6fx6z

eit6fx6z2#

对于像我这样认为最好的答案有点令人困惑的人来说,我发现__getattr__只期望返回它调用的可调用函数,并发送 * args和**kwargs。

def printf(name, *args, **kwargs):
    print(name)
    print(args)
    print(kwargs)

class MyClass:
    def __getattr__(self, name, *args, **kwargs):
        # *args and **kwargs are available here as lists and dictionaries, respectively
        # You can use them just like any other argument
        # For example, you can pass them to another function
        return printf

t = MyClass()

t.get("hello", "wow", headers ={"token": "123456789"})

输出:

hello  
('wow',)
{'headers': {'token': '123456789'}}

这就是我想要的,所以你需要用另一个函数来 Package 你的函数,以传递 * args和 * kwargs。

相关问题