python - 方法重载装饰器

标签 python decorator

我正在尝试编写一个为 python 提供方法重载功能的装饰器,类似于 PEP 3124 中提到的那个.

我编写的装饰器非常适合常规函数,但我无法让它用于类中的方法。

这是装饰器:

class Overload(object):
    def __init__(self, default):
        self.default_function = default
        self.type_map = {}
        self.pos = None

    def __call__(self, *args, **kwargs):
        print self
        try:
            if self.pos is None:
                pos = kwargs.get("pos", 0)
            else:
                pos = self.pos
            print args, kwargs
            return self.type_map[type(args[pos])](*args, **kwargs)
        except KeyError:
            return self.default_function(*args, **kwargs)
        except IndexError:
            return self.default_function(*args, **kwargs)

    def overload(self, *d_type):
        def wrapper(f):
            for dt in d_type:
                self.type_map[dt] = f
            return self
        return wrapper

当我尝试这样实现它时:

class MyClass(object):
    def __init__(self):
        self.some_instance_var = 1

    @Overload
    def print_first_item(self, x):
        return x[0], self.some_instance_var

    @print_first_item.overload(str)
    def print_first_item(self, x):
        return x.split()[0], self.some_instance_var

我在运行时遇到了一个TypeError:

>>> m = MyClass()
>>> m.print_first_item(1) 
<__main__.Overload object at 0x2> (1,) {} 
Traceback (most recent call last):   
  File "<stdin>", line 1, in <module>   
  File "overload.py", line 17, in __call__
    return self.default_function(*args, **kwargs) 
  TypeError: print_first_item() takes exactly 2 arguments (1 given)
>>>

我的问题是:如何从装饰方法中访问 MyClass 的实例(即 self)?

最佳答案

本质上,您的Overload 类需要一个__get__ 方法:

def __get__(self, obj, cls):
    # Called on access of MyClass.print_first_item.
    # We return a wrapper which calls our 
    print "get", self, obj, cls
    if obj is None:
        # a function would do some checks here, but we leave that.
        return self
    else:
        return lambda *a, **k: self(obj, *a, **k)

为什么?

好吧,您将Overload 对象用作一种函数替换。您希望它像函数一样在具有不同签名的方法上下文中表示自己。

简要说明方法访问的工作原理:

object.meth(1, 2)

被翻译成

object.__dict__['meth'].__get__(object, type(object))(1, 2)

函数的 __get__() 返回一个方法对象,该对象通过将对象添加到参数列表(结果为 self)包装函数:

realmethod = object.__dict__['meth'].__get__(object, type(object))
realmethod(1, 2)

其中 realmethod 是一个方法对象,它知道要调用的函数和要给它的 self 并通过转换调用适本地调用“真实”函数进入

meth(object, 1, 2)

.

我们在这个新的 __get__ 方法中模仿了这种行为。

关于python - 方法重载装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11371309/

相关文章:

python - 如何在 Python 中将全局标记为已弃用?

python - 使 'isinstance' 与装饰器一起工作

python - 将 bar_label 的格式更改为百分比

python - 从 gridsearchCV 内的 RFECV 检索选定的特征

python - 考虑语言环境对元组列表进行排序(瑞典顺序)

python - 在 virtualenv 中使用解释器时,IntelliJ IDEA 14 无法识别 Python 内置类型

java - 装饰器设计模式不明确

javascript - typescript 中的类装饰器

python - 列出 python 类中的 @property 装饰方法

python - Python如何知道类中的变量是方法还是变量?