1. <small id='NnfLC'></small><noframes id='NnfLC'>

    2. <legend id='NnfLC'><style id='NnfLC'><dir id='NnfLC'><q id='NnfLC'></q></dir></style></legend>
        <bdo id='NnfLC'></bdo><ul id='NnfLC'></ul>
      <tfoot id='NnfLC'></tfoot>

    3. <i id='NnfLC'><tr id='NnfLC'><dt id='NnfLC'><q id='NnfLC'><span id='NnfLC'><b id='NnfLC'><form id='NnfLC'><ins id='NnfLC'></ins><ul id='NnfLC'></ul><sub id='NnfLC'></sub></form><legend id='NnfLC'></legend><bdo id='NnfLC'><pre id='NnfLC'><center id='NnfLC'></center></pre></bdo></b><th id='NnfLC'></th></span></q></dt></tr></i><div id='NnfLC'><tfoot id='NnfLC'></tfoot><dl id='NnfLC'><fieldset id='NnfLC'></fieldset></dl></div>

      如何拦截对 python 的“魔术"的调用?新样式类中的方法?

      时间:2024-04-21

            <tbody id='UFq8L'></tbody>
        1. <i id='UFq8L'><tr id='UFq8L'><dt id='UFq8L'><q id='UFq8L'><span id='UFq8L'><b id='UFq8L'><form id='UFq8L'><ins id='UFq8L'></ins><ul id='UFq8L'></ul><sub id='UFq8L'></sub></form><legend id='UFq8L'></legend><bdo id='UFq8L'><pre id='UFq8L'><center id='UFq8L'></center></pre></bdo></b><th id='UFq8L'></th></span></q></dt></tr></i><div id='UFq8L'><tfoot id='UFq8L'></tfoot><dl id='UFq8L'><fieldset id='UFq8L'></fieldset></dl></div>
          <legend id='UFq8L'><style id='UFq8L'><dir id='UFq8L'><q id='UFq8L'></q></dir></style></legend>
        2. <tfoot id='UFq8L'></tfoot>

          <small id='UFq8L'></small><noframes id='UFq8L'>

            <bdo id='UFq8L'></bdo><ul id='UFq8L'></ul>

              1. 本文介绍了如何拦截对 python 的“魔术"的调用?新样式类中的方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                问题描述

                我正在尝试在新样式类中拦截对 python 双下划线魔术方法的调用.这是一个简单的例子,但它表明了意图:

                I'm trying to intercept calls to python's double underscore magic methods in new style classes. This is a trivial example but it show's the intent:

                class ShowMeList(object):
                    def __init__(self, it):
                        self._data = list(it)
                
                    def __getattr__(self, name):
                        attr = object.__getattribute__(self._data, name)
                        if callable(attr):
                            def wrapper(*a, **kw):
                                print "before the call"
                                result = attr(*a, **kw)
                                print "after the call"
                                return result
                            return wrapper
                        return attr
                

                如果我在列表周围使用该代理对象,我会得到非魔法方法的预期行为,但我的包装函数永远不会为魔法方法调用.

                If I use that proxy object around list I get the expected behavior for non-magic methods but my wrapper function is never called for magic methods.

                >>> l = ShowMeList(range(8))
                
                >>> l #call to __repr__
                <__main__.ShowMeList object at 0x9640eac>
                
                >>> l.append(9)
                before the call
                after the call
                
                >> len(l._data)
                9
                

                如果我不从对象继承(第一行 class ShowMeList:)一切都按预期工作:

                If I don't inherit from object (first line class ShowMeList:) everything works as expected:

                >>> l = ShowMeList(range(8))
                
                >>> l #call to __repr__
                before the call
                after the call
                [0, 1, 2, 3, 4, 5, 6, 7]
                
                >>> l.append(9)
                before the call
                after the call
                
                >> len(l._data)
                9
                

                如何使用新的样式类完成这种拦截?

                How do I accomplish this intercept with new style classes?

                推荐答案

                出于性能原因,Python 总是在类(和父类的)__dict__ 中查找魔术方法,而不使用普通的属性查找机制.一种解决方法是在创建类时使用元类自动为魔术方法添加代理;例如,我使用这种技术来避免为包装类编写样板调用方法.

                For performance reasons, Python always looks in the class (and parent classes') __dict__ for magic methods and does not use the normal attribute lookup mechanism. A workaround is to use a metaclass to automatically add proxies for magic methods at the time of class creation; I've used this technique to avoid having to write boilerplate call-through methods for wrapper classes, for example.

                class Wrapper(object):
                    """Wrapper class that provides proxy access to an instance of some
                       internal instance."""
                
                    __wraps__  = None
                    __ignore__ = "class mro new init setattr getattr getattribute"
                
                    def __init__(self, obj):
                        if self.__wraps__ is None:
                            raise TypeError("base class Wrapper may not be instantiated")
                        elif isinstance(obj, self.__wraps__):
                            self._obj = obj
                        else:
                            raise ValueError("wrapped object must be of %s" % self.__wraps__)
                
                    # provide proxy access to regular attributes of wrapped object
                    def __getattr__(self, name):
                        return getattr(self._obj, name)
                
                    # create proxies for wrapped object's double-underscore attributes
                    class __metaclass__(type):
                        def __init__(cls, name, bases, dct):
                
                            def make_proxy(name):
                                def proxy(self, *args):
                                    return getattr(self._obj, name)
                                return proxy
                
                            type.__init__(cls, name, bases, dct)
                            if cls.__wraps__:
                                ignore = set("__%s__" % n for n in cls.__ignore__.split())
                                for name in dir(cls.__wraps__):
                                    if name.startswith("__"):
                                        if name not in ignore and name not in dct:
                                            setattr(cls, name, property(make_proxy(name)))
                

                用法:

                class DictWrapper(Wrapper):
                    __wraps__ = dict
                
                wrapped_dict = DictWrapper(dict(a=1, b=2, c=3))
                
                # make sure it worked....
                assert "b" in wrapped_dict                        # __contains__
                assert wrapped_dict == dict(a=1, b=2, c=3)        # __eq__
                assert "'a': 1" in str(wrapped_dict)              # __str__
                assert wrapped_dict.__doc__.startswith("dict()")  # __doc__
                

                这篇关于如何拦截对 python 的“魔术"的调用?新样式类中的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                上一篇:TypeError:需要一个类似字节的对象,而不是 python 和 CSV 中的“str" 下一篇:在 Python 3.3 中与生成器一起返回

                相关文章

                <tfoot id='2vDUC'></tfoot>
              2. <small id='2vDUC'></small><noframes id='2vDUC'>

                1. <i id='2vDUC'><tr id='2vDUC'><dt id='2vDUC'><q id='2vDUC'><span id='2vDUC'><b id='2vDUC'><form id='2vDUC'><ins id='2vDUC'></ins><ul id='2vDUC'></ul><sub id='2vDUC'></sub></form><legend id='2vDUC'></legend><bdo id='2vDUC'><pre id='2vDUC'><center id='2vDUC'></center></pre></bdo></b><th id='2vDUC'></th></span></q></dt></tr></i><div id='2vDUC'><tfoot id='2vDUC'></tfoot><dl id='2vDUC'><fieldset id='2vDUC'></fieldset></dl></div>
                  • <bdo id='2vDUC'></bdo><ul id='2vDUC'></ul>

                    <legend id='2vDUC'><style id='2vDUC'><dir id='2vDUC'><q id='2vDUC'></q></dir></style></legend>