繁体   English   中英

Python:在“调用”class 中获取“调用者”class 实例并访问“调用者”实例变量

[英]Python: Get a 'caller' class instance in a 'calling' class and access 'caller's' instance variables

我需要在“调用”class 中获取“调用者”class 的实例。 我可以获取实例,我可以从“调用”class 调用“调用者”class 的方法,但我无法访问实例变量。 有谁知道这里的问题是什么以及如何解决它?

import inspect

class CallingClass():
    def __init__(self):
        prev_frame = inspect.currentframe().f_back
        caller = prev_frame.f_locals['self'].__class__
        print(f"The caller is {caller.__name__}")
        caller.test_f(caller)

class CallerClass():
    def __init__(self):
        self.value = 100
        i = CallingClass()

    def test_f(self):
        print("This line is fine.")
        print(f"The value is {self.value} but it will fail.")

if __name__ == "__main__":
    t = CallerClass()

output 是:

The caller is CallerClass
This line is fine.
Traceback (most recent call last):
  File "C:\test.py", line 20, in <module>
    t = CallerClass()
  File "C:\test.py", line 13, in __init__
    i = CallingClass()
  File "C:\test.py", line 8, in __init__
    caller.test_f(caller)
  File "C:\test.py", line 17, in test_f
    print(f"The value is {self.value} but it will fail.")
AttributeError: type object 'CallerClass' has no attribute 'value'

我很感激任何帮助。

您尚未实例化该实例。 prev_frame.f_locals['self'].__class__指的是实际的 class 类型(定义)。 我不相信你想创建一个新实例,但如果你这样做了,它看起来像这样:

caller = prev_frame.f_locals['self'].__class__()

但是,从代码片段中,我相信prev_frame.f_locals['self']会为您提供实例。

还值得指出的是,您使用“这条线很好”的唯一原因是因为您通过caller.test_f(caller)调用了它。 您将 class 定义传递给方法,占用所需的self参数。 如果您刚刚调用caller.test_f() (就像您实际上有一个实例一样),您就不会做到这一点,因为它会抱怨缺少必需的参数self

我不知道你想做什么,但我知道你做错了。

虽然导致代码错误的原因很容易修复,并且在调用 scope 中检索变量的部分工作正常,但您不应该在普通代码中这样做

一方面,Python 确实允许这样做,并且您使用的所有方法都记录在语言规范中,另一方面,内省调用函数作用域和变量的能力应该留给实现专门的代码这将做一些需要的事情——比如将以一种或另一种方式修改程序的某些运行时行为的库、日志记录工具或其他高级东西。

您的代码只是普通的调用代码,需要引用调用者 class 来更改某些属性。 简单明了的方法是将调用者实例作为显式参数传递给被调用者 class - 就是这样。 一切都用简单的属性处理,不需要自省:


class CallingClass():
    def __init__(self, parent):
        self.parent = parent
        print(f"The caller class is {type(self.parent)}")
        self.parent.test_f()

class CallerClass():
    def __init__(self):
        self.value = 100
        i = CallingClass(self)

    def test_f(self):
        print("This line is fine.")
        print(f"The value is {self.value} but it will work.")

if __name__ == "__main__":
    t = CallerClass()

现在,您的代码有什么问题,在应该留给高级和专用代码的框架自检和其他检查中,您误认为 class 是它的实例:您正在从 class 调用.test_f ,并通过 ZA2F2ED4F8EBC2CBBDC22ED4F8EBC2CBBDC1本身作为值,而不是反映在您读取的self变量中的实例。

class CallingClass():
    def __init__(self):
        prev_frame = inspect.currentframe().f_back
        caller_instance = prev_frame.f_locals['self']
        caller_class = caller_instance.__class__
        print(f"The caller is {caller_class.__name__}")
        caller_instance.test_f()

除此之外,我如此强调在这种情况下反对自省的原因之一是极端情况可能会从很多地方弹出:例如 - 在调用 scope 时变量可能不会被称为self ,或者,你不能这样在使用自省的方法中加一个装饰器,static分析软件如mypy不知道你在做什么等...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM