一千萬個為什麽

搜索

使用類/靜態方法作為同一類方法中的默認參數值

我想做這樣的事情:

class SillyWalk(object):
    @staticmethod
    def is_silly_enough(walk):
        return (False, "It's never silly enough")
    def walk(self, appraisal_method=is_silly_enough):
        self.do_stuff()
        (was_good_enough, reason) = appraisal_method(self)
        if not was_good_enough:
            self.execute_self_modifying_code(reason)
        return appraisal_method
    def do_stuff(self):
        pass
    def execute_self_modifying_code(self, problem):
        from __future__ import deepjuju
        deepjuju.kiss_booboo_better(self, problem)

這個想法是有人可以做的

>>> silly_walk = SillyWalk()
>>> appraise = walk()
>>> is_good_walk = appraise(silly_walk)

還有一些神奇的機器學習正在發生;最後一點對我來說並不是特別感興趣,這只是我發現的第一件事,它是在函數上下文和調用者的角度來舉例說明靜態方法的使用。

無論如何,這不起作用,因為 is_silly_enough 實際上不是一個函數:它是一個對象,其 __ get __ 方法將返回原始的 is_silly_enough 函數。這意味著它僅在作為對象屬性引用時以“正常”方式工作。有問題的對象是由 staticmethod()函數創建的,裝飾器放在 SillyWalkis_silly_enough 屬性和最初定義的函數之間用這個名字。

這意味著,為了在 SillyWalk.walk 其調用者中使用 appraisal_method 的默認值,我們必須要麽

  • call appraisal_method.__get__(instance, owner)(...) instead of just calling appraisal_method(...)
  • or assign it as the attribute of some object, then reference that object property as a method that we call as we would call appraisal_method.

Given that neither of these solutions seem particularly Pythonic™, I'm wondering if there is perhaps a better way to get this sort of functionality. I essentially want a way to specify that a method should, by default, use a particular class or static method defined within the scope of the same class to carry out some portion of its daily routine.

我不想使用 None ,因為我想允許 None 傳達不應該調用該特定函數的消息。我想我可以使用其他一些值,比如 FalseNotImplemented ,但似乎a)hackety b)很煩人必須編寫額外幾行代碼,如以及其他冗余文檔,對於看似可以非常簡潔地表達為默認參數的東西。

最好的方法是什麽?

最佳答案

我最終編寫了一個(un)包裝函數,用於函數定義頭文件,例如

def walk(self, appraisal_method=unstaticmethod(is_silly_enough)):

這實際上似乎有效,至少它使我的doctests在沒有它通過的情況下破壞。

這裏是:

def unstaticmethod(static):
    """Retrieve the original function from a `staticmethod` object.

    This is intended for use in binding class method default values
      to static methods of the same class.

    For example:
        >>> class C(object):
        ...     @staticmethod
        ...     def s(*args, **kwargs):
        ...         return (args, kwargs)
        ...     def m(self, args=[], kwargs={}, f=unstaticmethod(s)):
        ...         return f(*args, **kwargs)
        >>> o = C()
        >>> o.s(1, 2, 3)
        ((1, 2, 3), {})
        >>> o.m((1, 2, 3))
        ((1, 2, 3), {})
    """
    # TODO: Technically we should be passing the actual class of the owner
    #         instead of `object`, but
    #         I don't know if there's a way to get that info dynamically,
    #         since the class is not actually declared
    #         when this function is called during class method definition.
    #       I need to figure out if passing `object` instead
    #         is going to be an issue.
    return static.__get__(None, object)

更新:

我為 unstaticmethod 函數本身寫了doctests;他們也過去了。我仍然不完全確定這是一個真正聰明的事情,但它似乎確實有效。

轉載註明原文: 使用類/靜態方法作為同一類方法中的默認參數值