方法重载装饰器 [英] Method overloading decorator

查看:59
本文介绍了方法重载装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to write a decorator that provides method overloading functionality to python, similar to the one mentioned in PEP 3124.

我编写的装饰器对于常规函数非常有用,但是我无法将其用于类中的方法。

The decorator I wrote works great for regular functions, but I can't get it to work for methods in a class.

这里是装饰器:

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

当我尝试像这样实现它时:

When I attempt to implement it like this:

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 )是否来自修饰方法?

My question is: How can I access the instance of MyClass (i.e. self) from within the decorated method?

推荐答案

实质上,您的重载类需要一个 __ get __ 方法:

Essentially, your Overload class needs a __get__ method:

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)

为什么?

嗯,您使用超载对象作为一种功能替代。您希望它像函数一样在具有不同签名的方法上下文中表示自己。

Well, you use your Overload object as a kind of function replacement. You want it, like a function, to represent itself in a method context with different signature.

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

Short explanation how method access works:

object.meth(1, 2)

被转换为

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

函数的 __ get __()返回一个方法对象,该方法对象通过将对象放在参数列表之前来包装函数(在该列表中会导致 self ):

A function's __get__() returns a method object which wraps the function by prepending the object to the parameter list (where it results in self):

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

其中 realmethod 是一个方法对象,它知道要调用的函数以及 self 并通过将调用转换为

where realmethod is a method object which knows the function to be called and the self to be given to it and calls the "real" function appropriately by transforming the call into

meth(object, 1, 2)

我们在这种新的 __ get __ 方法中模仿的行为。

This behaviour we imitate in this new __get__ method.

这篇关于方法重载装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆