Как я могу получить имена методов, которые были связаны в классе? - PullRequest
2 голосов
/ 12 ноября 2019

Рассмотрим следующий пример кода, показывающий простой класс, который позволяет связывать методы, возвращая self.

import inspect

class classname(object):
    def __init__(self):
        self.hold = None

    def funcname(self):
        self.hold = 'a'
        return self

    def method(self, c):
        self.hold = self.hold * c
        return self


c = classname().funcname().method(10)

То, что я пытаюсь сделать, это проверить c таким образом, чтобы я мог видеть, что funcname и method были вызваны для этого класса.

Ответы [ 2 ]

1 голос
/ 12 ноября 2019

Это можно сделать, но не через inspect, поскольку сам экземпляр не запоминает эту историю. Вы должны добавить код для обслуживания звонков вручную.

class classname(object):
    def __init__(self):
        self.hold = None
        self.calls = []

    def funcname(self):
        self.hold = 'a'
        return self

    def method(self, c):
        self.hold = self.hold * c
        return self

    def __getattribute__(self, name):
        self_calls = object.__getattribute__(self, "__dict__")["calls"]
        self_calls.append(name)
        return object.__getattribute__(self, name)


c = classname().funcname().method(10)
print(c.calls)
0 голосов
/ 12 ноября 2019

Я написал библиотеку для такого рода вещей, которую я только что положил на GitHub на случай, если она кому-нибудь пригодится.

Она работает, оборачивая функции, классы илиобъекты с прокси, который регистрирует каждое взаимодействие. Это включает в себя не только имена методов, но также их аргументы и возвращаемые значения, и какие методы вызывали какие другие методы (в дереве).

Использование:

from tracer import tracer

@tracer
class classname(object):
    def __init__(self):
        self.hold = None

    def funcname(self):
        self.hold = 'a'
        return self

    def method(self, c):
        self.hold = self.hold * c
        return self

    def recursive_method(self, n):
        if n > 0:
            self.recursive_method(n - 1)
            self.recursive_method(n - 2)

c = classname().funcname().method(10)
c.recursive_method(3)

c.print_call_tree()

Вывод:

* +-> __init__()
  |
  +-> funcname() +-> <__main__.classname object at 0x0000000002A9EBA8>
  |
  +-> method(10) +-> <__main__.classname object at 0x0000000002AE2160>
  |
  +-> recursive_method(3) +-> recursive_method(2) +-> recursive_method(1) +-> recursive_method(0)
                          |                       |                       |
                          |                       |                       +-> recursive_method(-1)
                          |                       |
                          |                       +-> recursive_method(0)
                          |
                          +-> recursive_method(1) +-> recursive_method(0)
                                                  |
                                                  +-> recursive_method(-1)

Справедливое предупреждение: это немного хрупко, например, вы можете увидеть, что в журнале показаны разные идентификаторы для объекта, возвращаемого funcname и method, даже если это должен быть один и тот же объект стот же идентификатор.

...