方法调用本身而不使用方法名?

2024-04-26 04:29:15 发布

您现在位置:Python中文网/ 问答频道 /正文

class C:
  def M:
    self.M()

可以代替self.M,比如self.__FUNC__?因此,当函数名更改时,不会更改函数内部的代码


Tags: 函数代码selfdefclassfunc
1条回答
网友
1楼 · 发布于 2024-04-26 04:29:15

没有内置的功能,但是可以通过一个decorator来确保在每次调用原始函数之前定义属性。您还需要保存和恢复属性,以防多个方法被类似地修饰,并且它们彼此调用

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_不是绑定方法,因为在构造类时会调用decorator。这意味着self必须作为第一个参数显式地传递给该方法,无论何时从修饰的方法中调用它

更新

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

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!

相关问题 更多 >