我正在尝试编写一个为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
Run Code Online (Sandbox Code Playgroud)
当我尝试像这样实现它:
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
Run Code Online (Sandbox Code Playgroud)
我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)
>>>
Run Code Online (Sandbox Code Playgroud)
我的问题是:如何从装饰方法中访问MyClass(ie 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)
Run Code Online (Sandbox Code Playgroud)
为什么?
好吧,您使用Overload对象作为一种函数替换。您希望它像函数一样在具有不同签名的方法上下文中表示自身。
方法访问如何工作的简短说明:
object.meth(1, 2)
Run Code Online (Sandbox Code Playgroud)
被翻译成
object.__dict__['meth'].__get__(object, type(object))(1, 2)
Run Code Online (Sandbox Code Playgroud)
函数__get__()返回一个方法对象,该对象通过将对象添加到参数列表(结果为self)来包装函数:
realmethod = object.__dict__['meth'].__get__(object, type(object))
realmethod(1, 2)
Run Code Online (Sandbox Code Playgroud)
其中realmethod是一个方法对象,它知道要调用的函数和要self赋予它的函数,并通过将调用转换为适当地调用“真实”函数
meth(object, 1, 2)
Run Code Online (Sandbox Code Playgroud)
。
我们在这个新方法中模仿了这种行为__get__。
| 归档时间: |
|
| 查看次数: |
1478 次 |
| 最近记录: |