Функция модуля, статический метод, метод класса или отсутствие декораторов :Какая идиома более питоническая?

Я разработчик Java, который время от времени игрался с Python. Недавно я наткнулся на эту статью , в которой упоминаются распространенные ошибки, которые Java-программисты совершают, когда берутся за Python. Первое, что бросилось в глаза:

A static method in Java does not translate to a Python classmethod. Oh sure, it results in more or less the same effect, but the goal of a classmethod is actually to do something that's usually not even possible in Java (like inheriting a non-default constructor). The idiomatic translation of a Java static method is usually a module-level function, not a classmethod or staticmethod. (And static final fields should translate to module-level constants.)

This isn't much of a performance issue, but a Python programmer who has to work with Java-idiom code like this will be rather irritated by typing Foo.Foo.someMethod when it should just be Foo.someFunction. But do note that calling a classmethod involves an additional memory allocation that calling a staticmethod or function does not.

Oh, and all those Foo.Bar.Baz attribute chains don't come for free, either. In Java, those dotted names are looked up by the compiler, so at runtime it really doesn't matter how many of them you have. In Python, the lookups occur at runtime, so each dot counts. (Remember that in Python, "Flat is better than nested", although it's more related to "Readability counts" and "Simple is better than complex," than to being about performance.)

Я нашел это немного странным, потому что документация для staticmethod говорит:

Static methods in Python are similar to those found in Java or C++. Also see classmethod() for a variant that is useful for creating alternate class constructors.

Еще более загадочным является то, что этот код:

class A:
    def foo(x):
        print(x)
A.foo(5)

Не работает, как и ожидалось, в Python 2.7.3, но отлично работает в 3.2.3 (, хотя вы не можете вызвать метод для экземпляра A, только для класса.)

Таким образом, есть три способа реализации статических методов (, четыре, если считать с помощью classmethod ), каждый с небольшими отличиями, один из которых, по-видимому, не документирован. Кажется, это противоречит мантре Питона Должен быть один --и желательно только один --очевидный способ сделать это. Какая идиома наиболее питоническая? Каковы плюсы и минусы каждого?

Вот что я понял на данный момент:

Функция модуля:

  • Избегает проблемы Foo.Foo.f ()
  • Загрязняет пространство имен модуля больше, чем альтернативы
  • Нет наследства

статический метод:

  • Сохраняет функции, связанные с классом, внутри класса и вне пространства имен модуля.
  • Позволяет вызывать функцию для экземпляров класса.
  • Подклассы могут переопределить метод.

метод класса:

  • Идентичен staticmethod, но также передает класс в качестве первого аргумента.

Обычный метод (Только для Python 3):

  • Идентичен staticmethod, но не может вызывать метод для экземпляров класса.

Я слишком много думаю об этом? Это не проблема -? Пожалуйста помоги!

65
задан Doval 3 August 2012 в 01:50
поделиться