简体   繁体   English

在Python 2.3旧式mixin类中拦截__getattr__吗?

[英]Intercepting __getattr__ in a Python 2.3 old-style mixin class?

I have a large Python 2.3 based installation with 200k LOC. 我有一个基于Python 2.3的大型安装,具有200k LOC。 As part of a migration project I need to intercept all attribute lookups of all old-style class. 作为迁移项目的一部分,我需要拦截所有旧类的所有属性查找。

Old legacy code: 旧的旧版代码:

class Foo(Bar):
    ...

My idea is to inject a common mixin class like 我的想法是注入像

class Foo(Bar, Mixin):
    ...

class Mixin:

    def __getattr__(self, k)
        print repr(self), k
        return Foo.__getattr__(self, k)

However I am running always into a recursion because Foo.__getattr__ resolves to Mixin.__getattr__ . 但是,由于Foo.__getattr__解析为Mixin.__getattr__所以我总是遇到递归Mixin.__getattr__

Is there any way to fix the code for Python 2.3 old-style classes? 有什么方法可以修复Python 2.3旧式类的代码吗?

If you are already injecting mixins, why not add object as parent, to make them new style 如果您已经在注入mixin,为什么不添加object作为父object ,以使其具有新样式

class Foo(Mixin, Bar, object):
    ...

And then use super 然后用super

class Mixin(object):

    def __getattr__(self, k)
        print repr(self), k
        return super(Mixin, self).__getattr__(k)

Assuming that none of the classes in your code base implement __setattr__ or __getattr__ then one approach is to intercept __setattr__ in your Mixin, writing the value to another reserved attribute, then read it back in __getattr__ 假设您的代码库中没有一个类实现__setattr____getattr__则一种方法是在Mixin中拦截__setattr__ ,将值写入另一个保留属性,然后在__getattr__读回

class Mixin:
    def __setattr__(self, attr, value):
        # write the value into some special reserved space
        namespace = self.__dict__.setdefault("_namespace", {})
        namespace[attr] = value

    def __getattr__(self, attr):
        # reject special methods so e.g. __repr__ can't recurse
        if attr.startswith("__") and attr.endswith("__"):
            raise AttributeError

        # do whatever you wish to do here ...
        print repr(self), attr

        # read the value from the reserved space
        namespace = self.__dict__.get("_namespace", {})
        return namespace[attr]

Example: 例:

class Foo(Mixin):
    def __init__(self):
        self.x = 1

Then 然后

>>> Foo().x
<__main__.Foo instance at 0x10c4dad88> x

Clearly this won't work if any of your Foo classes implement __setattr__ or __getattr__ themselves. 显然,如果您的任何Foo类自己实现__setattr____getattr__则将无法使用。

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

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