статический метод как параметр по умолчанию для метода класса

Мой вопрос касается двух ответов на другой вопрос: Использование методов класса/статических методов в качестве значений параметров по умолчанию в методах того же класса.

Я пытаюсь понять, действительно ли есть разница между тем, что делают два ответа, и если да, то каковы плюсы и минусы каждого из них.

Вопрос: как использовать метод класса в качестве параметра по умолчанию для метода того же класса.

Ответ 1: используйте функцию вместо метода класса

class X:
    def default_func(x):
        return True

    def test(self, func = default_func):
        return func(self)

Ответ 2: используйте метод класса, но преобразуйте его в функцию

def unstaticmethod(static):
    return static.__get__(None, object)

class X:
    @staticmethod
    def default_func(x):
        return True

    def test(self, func = unstaticmethod(default_func)):
        return func(self)

Первоначально это было написано на Python 2, но мое резюме (надеюсь) на Python 3.


person max    schedule 19.10.2010    source источник


Ответы (1)


Ответ на самом деле зависит от того, какие другие намерения у вас есть в отношении X.default_func. Если вы хотите, чтобы X.default_func вызывался вне экземпляра X, то вы хотите, чтобы это был статический метод (ответ 2).

# in other code...
some_object = "Bring out your dead"
X.default_func(some_object)

Если, с другой стороны, вы не ожидаете, что default_func когда-либо будет вызываться, кроме как внутри экземпляра X (и, конечно, использоваться по умолчанию для test), я бы переписал ответ 1 как правильный метод (и используйте соглашение self).

class X:
    def default_func(self):
        return True

    def test(self, func = default_func):
        return func(self)

В качестве примечания я хотел бы отметить, что вы могли бы написать ответ 2 по-другому, чтобы избежать нестатического метода:

class X:
    def default_func(x):
        return True

    def test(self, func = default_func):
        return func(self)

    default_func = staticmethod(default_func)

Причина, по которой это работает, заключается в том, что класс X не создается (и default_func не становится методом X) до тех пор, пока не будет обработан весь блок под class X: (включая аргумент по умолчанию для test(func)).

person Jason R. Coombs    schedule 27.01.2011
comment
Я буду сбит с толку. Если default_func будет вызывается только внутри test(), но test() вызывается извне класса, как я могу сделать вызов извне класса, эквивалентный X().test(func=second_func ), где second_func — функция-член X. - person Charles Merriam; 26.11.2011
comment
В Python 2 нет понятия функции-члена. Классы и их экземпляры имеют только методы. Если second_func является обычным методом экземпляра, вам нужно будет получить базовую функцию, используя im_func: X().test(func=X.second_func.im_func). Я не рекомендую делать это. Если вам нужно выбирать методы динамически, вам, вероятно, лучше передать имена методов тестовой функции, затем сделать что-то вроде getattr(self, func_name)() в тесте и позволить Python выполнить привязку экземпляра. - person Jason R. Coombs; 01.12.2011