【问题标题】:Introspect calling object内省调用对象
【发布时间】:2011-09-01 15:06:53
【问题描述】:

如何从b.func()(即A 的实例的self)中内省A 的实例:

class A():
    def go(self):
        b=B()
        b.func()

class B():
    def func(self):
        # Introspect to find the calling A instance here

【问题讨论】:

  • 请注意,在 Python 2.x 中,最好从 object 继承而不是什么都不继承,这样您就可以使用 新型类
  • 没有可移植的方法来做到这一点(在 CPython 中做到这一点的唯一方法是抓取父框架并检查它,但并非所有 Python 实现都会公开这些数据)

标签: python introspection


【解决方案1】:

通过重构代码来做到这一点

class A():
    def go(self):
        b = B(self)
        b.func()

class B():
    def __init__(self, a):
        self.a = a

    def func(self):
        # Use self.a

class A():
    def go(self):
        b = B()
        b.func(self)

class B():
    def func(self, a):
        # a

【讨论】:

  • 其实有很多As可以调用B的实例。我不想将它们全部保存在 B 的实例中
  • @Johnathan,在示例 sn-p 中,B 由 A 创建,但不清楚它们是否被许多不同的 As 保存和使用。听起来您可能想在调用 B.func 时准确地传递正确的 A,就像在我的第二个示例中一样。
【解决方案2】:

一般来说,我们不希望func 能够访问A 的调用实例,因为这会破坏encapsulation。在b.func 内部,您应该可以访问任何传递的args 和kwargs、实例b 的状态/属性(通过self 此处),以及周围的任何全局变量。

如果您想了解调用对象,有效的方法是:

  1. 将调用对象作为参数传递给函数
  2. 在使用func 之前的某个时间,将调用者的句柄显式添加到b 实例上,然后通过self 访问该句柄。

然而,在排除了免责声明之后,仍然值得知道 python 的自省功能在某些情况下足以访问调用者模块。在 CPython 实现中,您可以在不更改接口的情况下访问调用 A 实例:

class A():
    def go(self):
        b=B()
        b.func()

class B():
    def func(self):
        import inspect
        print inspect.currentframe().f_back.f_locals['self']

if __name__ == '__main__':
    a = A()
    a.go()

输出:

<__main__.A instance at 0x15bd9e0>

这对于调试代码有时可能是一个有用的技巧。但是,在B.func 出于任何原因实际上需要使用A 的情况下,像这样访问堆栈帧并不是一个明智的设计决定。

【讨论】:

  • 这是脆弱的(有很多我们可以构建但它不起作用的案例)并且不可移植(inspect.currentframe 是一个实现细节)。
  • +1 用于回答问题(不管这样做是否明智)。这在哪里行不通?我怀疑关于 currentframe() 的“免责声明”是指 Stackless(不是 Jython 或 Iron Python)....任何人都可以证实这一点吗?
  • @Mike 你没抓住重点,我不是说你重写代码而不是pdb。假设您在 ipython 中,并且在 B.func 中得到一个未处理的异常。然后你可以使用魔法%debug 并且你在func 的体内。从那里你拥有解释器的全部功能,你可以输入import inspect 并做任何内省可能对你有帮助的事情。 一个工具可以被滥用并不意味着它不应该被使用
  • @wim 实际上,这些知识是否对发帖人有帮助,这取决于社区。这就是为什么它会受到反对。这些表明您发布的内容对于 OP 来说是一个糟糕的解决方案。
  • 我觉得这一切都令人惊讶。人们是否认为 Python 的自省能力应该保密,因为它通常不是正确的做法?只有一个答案给出了正确的事实,而人们却否决了它?事实就是事实。否决者反对透露这种“秘密知识”?你们都不知道OP为什么要找这个,因此你不能判断它是错误的。在某些情况下,这种内省肯定是有价值的。所以,恕我直言,可以警告它,但不应该因为揭示如何做到这一点而对 ans 投反对票。
【解决方案3】:

你将它作为参数传递给b.func()

【讨论】:

  • 这是我的解决方法,但我想知道如何避免这种情况
  • 这不是解决方法。这就是你给其他函数上下文的方式。
  • 我已经按照你的方式实现了它并继续进行,但我很想知道......此外我认为在我的特定设计中它可能更优雅
  • 您的具体设计是什么?不过,我严重怀疑它。 “显式优于隐式”
  • 同意。从技术上讲,您可以找到来电者,但b.func() 真的不知道是谁打来的
【解决方案4】:

我同意 Benjamin 的观点 - 将它作为参数传递给 b.func() 并且不要反省它!!!!

如果你的生活真的靠它,那我想你可以从this answer推导出答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-03
    • 2013-10-12
    • 1970-01-01
    • 2014-08-21
    • 2015-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多