Распечатайте аргументы и значения функций в методе __getattribute__ - PullRequest
0 голосов
/ 16 октября 2019

Я пытаюсь распечатать имя функции и аргументы, которые вызываются экземпляром каждый раз, когда экземпляр вызывает функцию

Я использую метод getattribute для реализации этого,мой код ниже

    def __getattribute__(self, attr):

        def newfunc(*args, **kwargs):

            print( "%r Calling %r with %r %r" % (self, attr, args, kwargs))


    return newfunc 

Код выводит имя и аргументы функции, но метод origin не выполняется, так как он возвращает новую функцию вместо вызова старой.

Я провел несколько поисков, например, вопрос , самый высокий голос в этом ответе, используя dict , чтобы получить функцию по ее имени в словаре, я попробовал это,но это приводит к рекурсивному вызову.

У меня вопрос. Есть ли способ вывести имя функции и аргументы внутри __getattribute__method?

или есть способ выводить имя и аргументы функции каждый раз, когда экземпляр вызывает ее метод?


Ps. кроме использования декораторов, я знал, что могу использовать декоратор для этого, но я не хочу ставить декоратор перед каждым методом, который я использую

Ответы [ 2 ]

0 голосов
/ 16 октября 2019

Поскольку вы не хотите применять декоратор, но вам все еще нужно "распечатать имя функции и аргументы внутри __getattribute__ метода" - используйте следующий подход:

Для того, чтобыво избежание бесконечной рекурсии в методе __getattribute__ его реализация всегда должна вызывать метод базового класса с тем же именем для доступа к любым необходимым атрибутам.

class A:
    def my_func(self, a, b):
        return a + b

    def __getattribute__(self, attr):
        def newfunc(*args, **kwargs):
            print("%r Calling %r with %r %r" % (self, attr, args, kwargs))

            return object.__getattribute__(self, attr)
        return newfunc

a = A()
a.my_func(1, 2)
a.my_func(3, 4)

Пример вывода:

<__main__.A object at 0x116861710> Calling 'my_func' with (1, 2) {}
<__main__.A object at 0x116861710> Calling 'my_func' with (3, 4) {}
0 голосов
/ 16 октября 2019

Основная и очевидная проблема с вашим кодом заключается в том, что вы ни разу не извлекаете исходный атрибут в экземпляре, который является задачей __getattribute__ - взлом __getattribute__ - это 100% мертвый способ сделать вашкласс вообще не работает.

Итак, во-первых, нужно вызвать рабочий __getattribute__ для суперкласса для извлечения атрибута.

Тогда вторая часть, которой явно не хватает в вашем коде, состоит в том, чтоВы даже не пытаетесь вызвать исходную функцию или метод из вашей функции «принтера». Мы помещаем такой вызов в конец его кода.

Это сделано, немного больше заботы, например, не пытаться возвращать не вызываемые атрибуты, заключенные в функцию, потому что это не получится.

После того, как вы позаботились об этих 3 пунктах, все должно работать так, как вы и предполагали:

def __getattribute__(self, attr):

    original = super().__getattribute__(attr)
    if callable(original):
        def newfunc(*args,  **kwargs):

            print( "%r Calling %r with %r %r" % (self, attr, args, kwargs))
            return original(*args, **kwargs)
        return newfunc
    return original

...