【问题标题】:How can i get the names of the methods that were chained in a class?如何获取类中链接的方法的名称?
【发布时间】:2019-11-11 23:07:37
【问题描述】:

考虑以下代码示例,该示例显示了一个简单的类,该类允许通过返回 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,以便我可以看到在这个类上调用了funcnamemethod

【问题讨论】:

  • 您不能,该对象不保留对此的记忆,您将不得不自己跟踪它。如果这是你必须知道的事情,这听起来像是你的设计的一个基本问题。
  • 感谢@juanpa.arrivillaga 的设计反馈。但是您正在对我对此类帖子的用例进行假设。如果无法完成,我理解,但必须有办法获取此信息。
  • 我并没有说这是不可能的,只是你必须自己跟踪这一点。您必须使用对象的内部状态手动跟踪正在调用的内容,例如调用列表,你可以编写一个 decotrator 来分解一些 biolerplate,并且更明确。

标签: python inspect


【解决方案1】:

可以做到,但不能通过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)

【讨论】:

  • 这正是我所追求的!谢谢!
【解决方案2】:

我已经为这类事情写了a library,我刚刚把它放在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)

公平警告:它有点脆弱,例如您可以看到日志显示 funcnamemethod 返回的对象的不同 id,即使它们应该是具有相同 id 的同一个对象。

【讨论】:

    猜你喜欢
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 2012-03-13
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    相关资源
    最近更新 更多