簡體   English   中英

沒有方法名的方法調用自身?

[英]Method call itself without method name?

class C:
  def M:
    self.M()

可以代替self.M ,像self.__FUNC__嗎? 所以當函數名改變時不會改變函數內部的代碼

沒有內置任何東西,但是您可以使用裝飾器來確保在每次調用原始函數之前定義屬性。 您還需要保存和恢復屬性,以防多個方法被類似地裝飾並且它們相互調用。

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必須將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!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM