Python:方法调用本身没有方法名称

时间:2014-08-17 16:11:02

标签: python

class C:
  def M:
    self.M()

可以代替self.M,而不是self.__FUNC__吗?所以当函数名称改变时不会改变函数内部的代码

1 个答案:

答案 0 :(得分:2)

没有任何内置功能,但您可以使用装饰器进行操作,以确保在每次调用原始函数之前定义属性。您还需要保存和恢复属性,以防多个方法进行类似的装饰,并且它们相互调用。

import functools

def decorator(func):
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        save = getattr(self, '_FUNC_', None)
        self._FUNC_ = func
        retval = func(self, *args, **kwargs)
        self._FUNC_ = save
        if save:  self._FUNC_ = save
        else: delattr(self, '_FUNC_')
        return retval
    return wrapper

class C(object):
    @decorator
    def M(self, i):
        if i > 0:
            print i,
            self._FUNC_(self, i-1)  # explicit 'self' argument required
        else:
            print '- Blast Off!'

C().M(3)  # -> 3 2 1 - Blast Off!

请注意self._FUNC_不是绑定方法,因为在构造类时会调用装饰器。这意味着只要在装饰方法中调用self,就必须将import functools def decorator(f): """ Method decorator specific to the instance. Uses a special descriptor to delay the definition of the method wrapper. """ class SpecialDescriptor(object): def __init__(self, f): self.f = f def __get__(self, instance, cls): if instance is None: # unbound method request? return self.make_unbound(cls) return self.make_bound(instance) def make_unbound(self, cls): @functools.wraps(self.f) def wrapper(*args, **kwargs): raise TypeError('unbound method {}() must be called with {} ' 'instance as first argument'.format( self.f.__name__, cls.__name__)) return wrapper def make_bound(self, instance): @functools.wraps(self.f) def wrapper(*args, **kwargs): save = getattr(instance, '_FUNC_', None) instance._FUNC_ = getattr(instance, self.f.__name__) retval = self.f(instance, *args, **kwargs) if save: instance._FUNC_ = save # restore any previous value else: delattr(instance, '_FUNC_') return retval # instance no longer needs special descriptor, since method is now # wrapped, so make it call the wrapper directly from now on setattr(instance, self.f.__name__, wrapper) return wrapper return SpecialDescriptor(f) class C(object): @decorator def M(self, i): if i > 0: print i, self._FUNC_(i-1) # No explicit 'self' argument required else: print '- Blast Off!' C().M(3) # -> 3 2 1 - Blast Off! 作为第一个参数显式传递给方法。

<强>更新

解决这个问题的一种方法是在第一次实际调用该方法之前不创建包装函数(然后保存它以减少将来的开销)。这将允许像任何其他方法一样调用它。我想到了一个名为PythonDecoratorLibraryClass method decorator using instance示例的解决方案。

{{1}}