дизайн класса Python (статический метод против метода) - PullRequest
7 голосов
/ 06 марта 2011

Что лучше для методов, которым не нужна передаваемая информация (экземпляр объекта или класс), потому что, например, они просто выполняют простое преобразование. @ staticmethod или метод ?

class Foo(object):
    def __init__(self, trees):
        self.money = Foo.trees2money(trees)

    @staticmethod
    def trees2money(trees):
        return trees * 1.337

class Quu(object):
    def __init__(self, trees):
        self.money = self.trees2money(trees)

    def trees2money(self, trees):
        return trees * 1.337

Ответы [ 3 ]

8 голосов
/ 06 марта 2011

Выбор типа метода зависит от других факторов.

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

В этом первом случае вы часто либо используете обычный метод (это когда метод относится к экземплярам, ​​а не к классу), либо classmethod (когда метод относится к классу, например, это альтернатива конструктор, метод обнаружения особенностей класса и т. д.). В обоих случаях вы можете использовать staticmethod вместо этого, если никакая информация из класса / экземпляра не используется методом, но вы ничего не получите от этого. И это также сломало бы вашу способность делать cls.method(instance, *args), что уже слишком много, чтобы ничего не получить.

Второй случай, когда метод никоим образом не является частью класса. Тогда обычно рекомендуется использовать функцию - метод на самом деле не является частью интерфейса, поэтому ему там не место. Ваш пример, кажется, является тем случаем, если вы не хотите переопределять калькулятор дерева / денег в подклассах, но это во многом зависит от того, что вы делаете с ним.

Особый случай - это закрытые методы - тогда вы можете захотеть использовать метод, даже если он на самом деле не связан с классом, закрытые методы не являются частью интерфейса, поэтому не имеет значения, куда вы их помещаете. Использование staticmethod все еще мало что дает вам, но также нет никаких причин не использовать его.

В действительности есть один случай, когда staticmethod очень полезен - когда вы помещаете внешние функции (или другие объекты) в класс.

class Foo(object):
     trees2money = staticmethod(calculators.trees2money)
     foo = staticmethod(calculators.bar)

Но когда у вас есть статическое определение класса, это не очень хорошо, потому что вы всегда можете вместо этого сделать следующее.

class Foo(object):
     def trees2money(self, trees):
         """Calculator for trees2money, you can override when subclassing"""
         return calculators.trees2money(trees)
     @property
     def foo(self):
         """The foo of the object"""
         return calculators.bar

Что дает вам лучшее представление о том, что делают эти объекты при чтении исходного кода, и даже позволяет добавлять документацию. Но это все еще может пригодиться, когда вы динамически создаете классы или добавляете их в метакласс (создание метода-оболочки вручную не очень удобно).

2 голосов
/ 06 марта 2011

Мое общее правило для всех объектно-ориентированных проектов заключается в том, что если у класса нет состояния, рассмотрите возможность использования статических методов. Если у класса есть состояние, используйте методы экземпляра - hands down.

Кроме того, если у класса действительно нет состояния, подумайте несколько минут и посмотрите, нельзя ли приблизить статическое поведение к данным и тем самым исключить эти статические методы с помощью Извлечения метода рефакторинг.

0 голосов
/ 06 марта 2011

Любые методы, которые не используют имена из пространства имен объекта, должны быть методами класса, а те, которые не используют имена из пространства имен класса, - staticmetdods или даже помещаться на уровень модуля в качестве функций.

Когда используется фактический метод объекта, ожидаемое поведение - доступ к некоторым другим атрибутам / методам из того же объекта.

...