Я разработчик Java, который играл и запускал Python. Недавно я наткнулся на эту статью, в которой упоминаются распространенные ошибки, которые программисты Java делают, когда они забирают Python. Первый попался на глаза:
Статический метод в Java не переводит на класс класса Python. О, конечно, это приводит к более или менее такому же эффекту, но цель classmethod - фактически делать то, что обычно не возможно даже в Java (например, наследование конструктора, отличного от стандартного). Идиоматический перевод статического метода Java обычно является функцией уровня модуля, а не классом или статическим методом. (И статические конечные поля должны переводить на константы уровня модуля.)
Это не большая проблема производительности, но программист на Python, который должен работать с кодом Java-идиомы, подобным этому, будет довольно раздражен, набрав Foo.Foo.someMethod, когда он должен быть просто Foo.someFunction. Но имейте в виду, что вызов метода класса предполагает дополнительное выделение памяти, которое вызывает метод static или метод.
О, и все эти цепи атрибутов Foo.Bar.Baz также не предоставляются бесплатно. В Java эти точечные имена просматриваются компилятором, поэтому во время выполнения действительно не имеет значения, сколько из них у вас есть. В Python поиск выполняется во время выполнения, поэтому каждая точка подсчитывается. (Помните, что в Python "Плоский лучше, чем вложенный", хотя он больше связан с "Подсчитываемыми коэффициентами" и "Простым лучше, чем сложным", чем с представлением о производительности.)
Я нашел это немного странным, потому что документация для staticmethod говорит:
Статические методы в Python аналогичны тем, которые существуют в Java или С++. Также см. Classmethod() для варианта, который полезен для создания альтернативных конструкторов классов.
Еще более озадачивающим является то, что этот код:
class A:
def foo(x):
print(x)
A.foo(5)
Сбой, как и ожидалось, в Python 2.7.3, но отлично работает в 3.2.3 (хотя вы не можете вызывать метод в экземпляре A только для класса.)
Итак, существует три способа реализации статических методов (четыре, если вы считаете, используя метод класса), каждый из которых имеет тонкие отличия, один из которых, по-видимому, недокументирован. Это, похоже, противоречит мантре Python . Должен быть один - и желательно только один - простой способ сделать это. Какая идиома является самой Pythonic? Каковы плюсы и минусы каждого?
Вот что я понимаю до сих пор:
Функция модуля:
- Предотвращает проблему Foo.Foo.f()
- Загрязняет пространство имен модулей больше, чем альтернативы
- Наследование отсутствует
STATICMETHOD:
- Сохраняет функции, связанные с классом внутри класса и из пространства имен модулей.
- Позволяет вызывать функцию в экземплярах класса.
- Подклассы могут переопределять метод.
classmethod:
- Идентично для staticmethod, но также передает класс в качестве первого аргумента.
Обычный метод (только для Python 3):
- Идентичен для staticmethod, но не может вызвать метод для экземпляров класса.
Могу ли я это высказать? Это не проблема? Пожалуйста, помогите!