从框架中检测方法与哪个类别相关联

时间:2018-08-28 14:56:00

标签: python super internal sys python-3.7

我正在用Python编写令人难以置信的令人难以置信的代码,我需要某种方法来检测是否从{{1}类上定义的方法调用了_XYZ__foo属性访问}}。但是,这并不那么容易,因为如果任何东西都覆盖了/_*XYZ/并称为__getattribute__,我需要检测原始方法的访问权限。

我不擅长解释,因此...规则类似于Java的super(),只是我想防止作弊。 (是的,我知道这与Python的哲学背道而驰;在这里忍受。)

我当前的攻击计划是:

  1. 使用private检测类的名称(前面的re.compile('_(?P<class>.*?)__(?P<name>.*)')被去除)。
  2. _爬上super链,以找出属性访问的位置。
  3. 以某种方式检测上了什么课。我被困在这里。

我也许可以通过模拟sys._getframe(n)的MRO来做到这一点,但是我宁愿依靠检测,因为要检查super所调用的内容以及用户所调用的内容功能很难。

对我的实际问题。给定框架,我如何检测方法与哪个类关联?如果我可以访问该功能对象,那么我可以super进行操作,但是我不能(或者至少我不认为我可以这样做)。就那样,我不知道该怎么做!

这是一个简单的示例,演示了我想要做什么:

f.__qualname__[:-1-len(f.__name__)]

1 个答案:

答案 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