python 每次调用类中的方法时运行一个函数

t1rydlwq  于 12个月前  发布在  Python
关注(0)|答案(1)|浏览(99)

我试图为类中的每个函数创建一个方法,每次调用函数时都会调用该方法。这个类是另一个类的子类(在我的特定例子中,它是list的子类)。

class Foo(another_class):
    def __init__(self, bar):
        self.bar = bar
        super().__init__(self.bar)

    def function_to_be_called(self):
        self.bar += 1

    def function(self):
        # do stuff

foo = Foo(0)
foo.function()
foo.inherited_function()
print(foo.bar)  # should be 2, since function and inherited_function were called

我发现an answer建议覆盖__getattribute__魔术方法,但这样做会导致无限递归(因为调用的函数需要首先使用__getattribute__找到),或者产生非常奇怪的行为。
我的第一次尝试(导致RecursionError):

class Foo(another_class):
    def __init__(self, bar):
        self.bar = bar
        super().__init__(self.bar)

    def function_to_be_called(self):
        self.bar += 1

    def function(self):
        # do stuff

    def __getattribute__(self, attr):
        method = another_class.__getattribute__(self, attr)
        self.function_to_be_called()  # this required __getattribute__ to be called to find function_to_be_called, causing an infinite loop
        # even if self.function_to_be_called() is replaced with the self.bar += 1, it still causes an infinite loop as __getattribute__  is called to find bar
        return method

我的第二次尝试还包括答案中的if callable(method),并将function_to_be_called的内容移动到if语句中,而不是调用函数(p.s.我将酒吧改为列表,因为这是我的初衷,也是我发现奇怪行为的原因):

# Assume that another_class has an append method
class Foo(another_class):
    def __init__(self, bar):
        self.bar = bar
        super().__init__(self.bar)

    def function(self):
        print(self.bar)

    def __getattribute__(self, attr):
        method = another_class.__getattribute__(self, attr)
        if callable(method):
            self.bar.sort()  # doing something to bar, for example sorting it
        return method

foo = Foo([3, 1, 2])
print(foo)  # [3, 1, 2], although the expected result is [1, 2, 3]. it does not actually seem to be sorting it
foo.append(1)
print(foo)  # [3, 1, 2, 1], although the expected result is [1, 1, 2, 3]
foo.function()  # [1, 2, 3], the other 1 that was appended dissappears randomly (edit: I tried this again, with the actual class that I am using this in, and it seems to work for some reason), and it is sorted for some reason this time
f45qwnt8

f45qwnt81#

您可以调用super().__getattribute__方法(在本例中解析为object.__getattribute__方法)来避免递归:

class Foo(list):
    def __init__(self, seq):
        super().__init__(seq)
        self.bar = 0

    def function_to_be_called(self):
        self.bar += 1

    def function(self):
        pass

    def __getattribute__(self, name):
        attr = super().__getattribute__(name)
        if callable(attr):
            super().__getattribute__('function_to_be_called')()
        return attr

foo = Foo([3, 1, 2])
foo.append(1)
foo.function()
print(foo.bar)

该输出:

2

Demo:在线试用!

相关问题