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 的“魔术"的调用?新样式类中的方法?

      How can I intercept calls to python#39;s quot;magicquot; methods in new style classes?(如何拦截对 python 的“魔术的调用?新样式类中的方法?)

            <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 的“魔术"的调用?新样式类中的方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

                相关文档推荐

                Split a Pandas column of lists into multiple columns(将 Pandas 的列表列拆分为多列)
                How does the @property decorator work in Python?(@property 装饰器在 Python 中是如何工作的?)
                What is the difference between old style and new style classes in Python?(Python中的旧样式类和新样式类有什么区别?)
                How to break out of multiple loops?(如何打破多个循环?)
                How to put the legend out of the plot(如何将传说从情节中剔除)
                Why is the output of my function printing out quot;Nonequot;?(为什么我的函数输出打印出“无?)
                <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>
                          <tbody id='2vDUC'></tbody>