Причиной возникновения проблем с использованием статического метода в качестве аргумента по умолчанию является комбинация двух проблем.
Первая проблема заключается в том, что аргумент по умолчанию должен быть четко определен, когда *Оператор 1003 * выполняется не только при вызове функции.Это потому, что аргумент по умолчанию встроен в объект функции, а не пересчитывается при каждом запуске функции (это та же самая причина, по которой изменяемый аргумент по умолчанию, такой как пустой список, часто является ошибкой).В любом случае, именно поэтому вы не можете использовать MyClass.static_method
в качестве аргумента по умолчанию, поскольку MyClass
еще не определено, когда определяется функция (объект класса создается только после того, как все его содержимое создано).
Следующая проблема заключается в том, что объект staticmethod
не имеет все те же атрибуты и методы, что и обычная функция.Обычно это не имеет значения, поскольку, когда вы обращаетесь к нему через объект класса (например, MyClass.static_method
, если существует MyClass
) или через экземпляр (например, self.static_method
), он будет вызываться и иметь __name__
.Но это потому, что в этих ситуациях вы получаете основную функцию, а не сам объект staticmethod
.Сам объект staticmethod
является дескриптором, но не вызываемым.
Так что ни одна из этих функций не будет работать правильно:
class MyClass:
@staticmethod
def static_method():
pass
def foo(self, func=MyClass.static_method): # won't work because MyClass doesn't exist yet
pass
def bar(self, func=static_method): # this declaration will work (if you comment out foo)
name = func.__name__ # but this doesn't work when the bar() is called
func() # nor this, as func is the staticmethod object
Что будет работать, если использовать фактическую функцию, лежащую в основеstaticmethod
объект по умолчанию:
def baz(self, func=static_method.__func__): # this works!
name = func.__name__
func()
Это также работает, когда вы передаете какую-то другую функцию (или связанный метод), в отличие от версии вашего кода, которая использовала name = func.__func__.__name__
.