考虑等,其是通过用Cython运行并编译成一个扩展模块转换内建函数类型方法类型(在Python 3)
def increment(self):
self.count += 1
一个简单的函数。假设现在我想让这个函数成为一个类的方法。例如:
class Counter:
def __init__(self):
self.count = 0
from compiled_extension import increment
Counter.increment = increment
现在这将无法正常工作,因为C级调用约定将被打破。例如:
>>> c = Counter()
>>> c.increment()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: increment() takes exactly one argument (0 given)
但是在Python 2中,我们可以通过执行功能转换为不受约束的方法:
Counter.increment = types.MethodType(increment, None, Counter)
如何可以完成同样的事情在Python 3?
一个简单的方法是使用超薄包装:
from functools import wraps
def method_wraper(f):
def wrapper(*args, **kwargs):
return f(*args, **kwargs)
return wraps(f)(wrapper)
Counter.increment = method_wrapper(increment)
有没有更有效的方式来做到这一点?
我有这个问题尝试使用丑'heapq'模块构建Heapq类。你的解决方案很好。它可以在一行中完成,但具有相同的效率:'def method_wraper(f):return functools.wraps(f)(lambda * a,** kw:f(* a,** kw))' – JBernardo
。有趣的是,如果函数是在同一个模块中定义的(分配给一个类并绑定在实例化上的未绑定方法),赋值似乎可以正常工作。所以这只是C扩展的一个问题,或者与不同模块中的函数有关?无论如何,你可能想看看http://stackoverflow.com/questions/7490879/python3-bind-method-to-class-instance-with-get-it-works-but-why,这可以帮助你一点点以及。 – JAB
另外,http://docs.python.org/py3k/howto/descriptor.html#functions-and-methods“对象/ classobject.c中PyMethod_Type的实际C实现是一个具有两个不同表示的对象,具体取决于是否im_self字段被设置或者为NULL(C的等效值为None)。“这使得看起来应该不会发生这个问题,除非Python在实例化对象时以某种方式不直接更新对象方法的该字段。 – JAB