检查一个方法是否从类内部调用。
检查一个方法是否从类内部调用。
最近的一个问题引起了我的兴趣,即我们是否可以在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
- 自回答发布以来有些改变?
- 我可能遗漏了一些关键细节
\n
\n
\n由于我的代码与上述答案中的代码非常相似,我会假设问题与Python的版本有关。\n因此,我的问题是,如何检查方法是从哪个类调用的?是否有其他方法可以实现?但最重要的是,为什么这段代码不起作用?
尽管这个任务被认为是不可能的,但是似乎可以通过简单地用f_locals['self']
代替__self__
来轻松实现我想要的行为。
当前的代码本不应该正常工作,因为frame对象本身没有__self__
属性,并且不会返回该frame的类 - 这是我从前面的答案中假设的。
你会发现,与适当的私有变量功能不同,这允许从子类和超类方法访问,但禁止从staticmethods、classmethods或从不同实例调用的实例方法访问。此外,它无法阻止从类外部设置属性,并且可以通过调用object.__getattribute__
等多种方式轻松绕过。这比只是在属性前加上__
要差得多,从很多方面看都是如此。
这个问题从来不是关于这个方法有多好,只是关于我在尝试实现它时遇到的错误。找出从哪个类调用函数可能有无数其他用途,这只是其中之一。
除了...它并没有找出访问发生的类。最好的情况是,如果一切顺利,你有了发生访问的方法所属实例。这并不能告诉你类。
为了尝试找到类,你可以检查调用帧的代码对象,并尝试确定它在哪个类中定义。然而,这也有很多失败点。
嗯,这个解决方案产生了我想要的精确输出,到目前为止是唯一的解决方案。如果有其他方法可以以其他方式实现相同的目标,我很愿意将该答案标记为更好的答案。