我正在用Python编写令人难以置信的令人难以置信的代码,我需要某种方法来检测是否从{{1}类上定义的方法调用了_XYZ__foo
属性访问}}。但是,这并不那么容易,因为如果任何东西都覆盖了/_*XYZ/
并称为__getattribute__
,我需要检测原始方法的访问权限。
我不擅长解释,因此...规则类似于Java的super()
,只是我想防止作弊。 (是的,我知道这与Python的哲学背道而驰;在这里忍受。)
我当前的攻击计划是:
private
检测类的名称(前面的re.compile('_(?P<class>.*?)__(?P<name>.*)')
被去除)。_
爬上super
链,以找出属性访问的位置。我也许可以通过模拟sys._getframe(n)
的MRO来做到这一点,但是我宁愿依靠检测,因为要检查super
所调用的内容以及用户所调用的内容功能很难。
对我的实际问题。给定框架,我如何检测方法与哪个类关联?如果我可以访问该功能对象,那么我可以super
进行操作,但是我不能(或者至少我不认为我可以这样做)。就那样,我不知道该怎么做!
这是一个简单的示例,演示了我想要做什么:
f.__qualname__[:-1-len(f.__name__)]
答案 0 :(得分:1)
据我所知,无法获得直接从框架对象进行属性访问的方法。但是,我们可以获得该方法的code object。然后,我们可以搜索对象的MRO,直到找到该代码对象所属的方法为止。
private_regex = re.compile('_(?P<class>.*?)__(?P<name>.*)')
class HackishClass:
__slots__ = ()
def __getattribute__(self, key):
match = private_regex.match(key)
if match is None:
# not a private attribute, no problem
return super().__getattribute__(key)
# obtain the code object of the calling function
calling_codeobj = inspect.currentframe().f_back.f_code
# iterate the MRO until we find a class with the name from `key`
classname = match.group('class')
for cls in type(self).mro():
if cls.__name__ != classname:
continue
# check if the code object belongs to a method defined in this class
for thing in vars(cls).values():
if getattr(thing, '__code__', None) is calling_codeobj:
# found it! allow the attribute access
return super().__getattribute__(key)
raise AttributeError("This is private! Keep out.")
一个小示范:
class Foo:
def __init__(self):
self.__foo = 5
print(self.__foo)
f = Foo() # prints 5
print(f._Foo__foo) # throws AttributeError