内省调用对象

发布于 2024-12-02 09:23:15 字数 305 浏览 0 评论 0原文

如何从 b.func() 内省 A 的实例(即 A 的实例的 self< /代码>):

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

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

How do I introspect A's instance from within b.func() (i.e. A's instance's self):

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冷血 2024-12-09 09:23:15

一般来说,我们不希望 func 能够访问 A 的调用实例,因为这会破坏 封装。在 b.func 内部,您应该可以访问传递的任何参数和 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>

这可能是出于调试目的需要了解的有用技巧。类似的技术甚至在 stdlib logging 中使用,此处,以便记录器能够发现源代码/文件名/行号/函数名称,而无需显式传递该上下文。但是,在正常使用情况下,在 B.func 实际上需要使用 A 的情况下访问堆栈帧通常不是明智的设计决策,因为它更干净并且更容易传递您需要的信息,而不是尝试“回复”呼叫者。

In general we don't want that func to have access back to the calling instance of A because this breaks encapsulation. Inside of b.func you should have access to any args and kwargs passed, the state/attributes of the instance b (via self here), and any globals hanging around.

If you want to know about a calling object, the valid ways are:

  1. Pass the calling object in as an argument to the function
  2. Explicitly add a handle to the caller onto b instance sometime before using func, and then access that handle through self.

However, with that disclaimer out of the way, it's still worth knowing that Python's introspection capabilities are powerful enough to access the caller module in some cases. In the CPython implementation, here is how you could access the calling A instance without changing your existing function signatures:

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()

Output:

<__main__.A instance at 0x15bd9e0>

This might be a useful trick to know about for debugging purposes. A similar technique is even used in stdlib logging, here, so that loggers are able to discover the source code/file name/line number/function name without needing to be explicitly passed that context. However, in normal use cases, it would not usually be a sensible design decision to access stack frames in the case that B.func actually needed to use A, because it's cleaner and easier to pass along the information that you need rather than to try and "reach back" to a caller.

倒带 2024-12-09 09:23:15

您将其作为参数传递给 b.func()

You pass it to b.func() as an argument.

魄砕の薆 2024-12-09 09:23:15

通过重构您的代码来实现此目的,使其工作方式类似于

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

Do this by refactoring your code to work like

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

or

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

class B():
    def func(self, a):
        # a
失而复得 2024-12-09 09:23:15

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

如果你的生活真的取决于它,那么我认为你可以从 这个答案

I agree with Benjamin - pass it to b.func() as an argument and don't introspect it!!!!

If your life really depends on it, then I think you can deduce the answer from this answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文