方法重载装饰器 [英] Method overloading decorator
问题描述
我正在尝试编写一个装饰器,为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屋!