检查一个方法是否从类内部调用。

7 浏览
0 Comments

检查一个方法是否从类内部调用。

最近的一个问题引起了我的兴趣,即我们是否可以在Python中模拟私有变量的行为。我尝试使用inspect模块来实现这个目标。\n我的计划是检查__getattribute__方法是否是从类内部调用的,类似于这个答案的做法。\n据我理解,我可以使用f_back获取下一个外部帧对象,直到最终到达调用它的类。令我惊讶的是,所有对frame.__self__的调用都导致AttributeError,直到我通过过多地调用f_back最终到达None为止:\n

import inspect
class MyClass:
    def __init__(self):
        self.variable = 1
    def __getattribute__(self, attr):
        frame = inspect.currentframe()
        try:
            while frame != None:
                try:
                    frame.__self__ # 我可以这样做吗?
                    print("Yes I can")
                except AttributeError:
                    print("Nope")
                frame = frame.f_back
        finally:
            del frame
        return super().__getattribute__(attr)
    def get_variable(self):
        return self.variable
A = MyClass()
print(A.get_variable())

\n尽管getter方法从类内部调用__getattribute__,但我只得到了\"Nope\",(我认为逐帧往回追溯应该会到达调用它的类)我可以想到两种可能性解释为什么这不起作用。\n

    \n

  1. 自回答发布以来有些改变?
  2. \n

  3. 我可能遗漏了一些关键细节
  4. \n

\n由于我的代码与上述答案中的代码非常相似,我会假设问题与Python的版本有关。\n因此,我的问题是,如何检查方法是从哪个类调用的?是否有其他方法可以实现?但最重要的是,为什么这段代码不起作用?

0
0 Comments

尽管这个任务被认为是不可能的,但是似乎可以通过简单地用f_locals['self']代替__self__来轻松实现我想要的行为。

当前的代码本不应该正常工作,因为frame对象本身没有__self__属性,并且不会返回该frame的类 - 这是我从前面的答案中假设的。

你会发现,与适当的私有变量功能不同,这允许从子类和超类方法访问,但禁止从staticmethods、classmethods或从不同实例调用的实例方法访问。此外,它无法阻止从类外部设置属性,并且可以通过调用object.__getattribute__等多种方式轻松绕过。这比只是在属性前加上__要差得多,从很多方面看都是如此。

这个问题从来不是关于这个方法有多好,只是关于我在尝试实现它时遇到的错误。找出从哪个类调用函数可能有无数其他用途,这只是其中之一。

除了...它并没有找出访问发生的类。最好的情况是,如果一切顺利,你有了发生访问的方法所属实例。这并不能告诉你类。

为了尝试找到类,你可以检查调用帧的代码对象,并尝试确定它在哪个类中定义。然而,这也有很多失败点。

嗯,这个解决方案产生了我想要的精确输出,到目前为止是唯一的解决方案。如果有其他方法可以以其他方式实现相同的目标,我很愿意将该答案标记为更好的答案。

0