Где поместить разделение между объектом с состоянием и вычислением без состояния в Python? - PullRequest
1 голос
/ 09 марта 2010

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

class A(object):
    """Freely mix state and calcs - no good I presume"""
    def __init__(self, state):
        self.state = state

    def calc_with_state(self, x):
        return (self.state + x)**2

или

class B(object):
    """Separate state from calc by a static method"""
    @staticmethod
    def inner_calc(u, v):
        return (u + v)**2

    def __init__(self, state):
        self.state = state

    def calc_with_state(self, x):
        return B.inner_calc(self.state, x)

или

class C(object):
    """Break out the calculation in a free function"""
    def __init__(self, state):
        self.state = state

    def calc_with_state(self, x):
        return outer_calc(self.state, x)

def outer_calc(u, v):
    return (u + v)**2

Ответы [ 5 ]

6 голосов
/ 09 марта 2010

Как написано, А, по длинному снимку. Вопрос довольно прост:

Квартира лучше вложенной.

Посмотрите: отделение состояния от вычислений - это хороший принцип проектирования, но это не означает, что вы думаете, по крайней мере, не то, что я могу вывести из этого примера. Мы хотим убедиться, что состояние не изменяется , чтобы завершить вычисления, если это состояние не будет повторно инициализировано при следующем вычислении. Если состояние доступно только для чтения в отношении какого-то конкретного вычисления, нет стилистического принуждения, чтобы перенаправить его вокруг, чтобы вы не читали его напрямую. То есть, если только вычисления и состояния не являются достаточно сложными, чтобы требовать отдельного модульного тестирования. Тогда, во что бы то ни стало, B или C предпочтительнее, но только в том случае, если действительно гораздо проще создать значения для u, чем создавать новые экземпляры A.

1 голос
/ 09 марта 2010

Я думаю, это зависит от вашего конкретного проекта. cal_with_state применимо только к этому конкретному классу или метод должен быть разделен между многими различными объектами? Разные классы разделяют это?

Нет ничего более-менее питонического в любом из этих подходов, используйте тот, который удовлетворит ваш проект. СУХОЙ за пределами питоничности.

0 голосов
/ 09 марта 2010

Что не так с А? Он выполняет вычисления только в одном месте и не изменяет состояние, поэтому calc_with_state - это метод, который не изменяет состояние, а также «простое» поведение. Если состояние было сложным, оно останавливает передачу большого количества параметров в функцию расчета.

Однако, если вычисление может быть записано с использованием состояния в качестве параметра (как в C), вы можете отделить вычисление. Преимущества здесь включают возможность рутировать этот расчет для данных, не относящихся к классу C, а также вы можете использовать функцию в качестве данных, передаваемых в C, так что calc_with_state может быть использован для вызова различных функций вычислений

Я не вижу, чтобы B имел какие-либо преимущества, так как inner_calc не использует класс и поэтому вполне может быть бесплатной функцией.

Так что я бы, вероятно, сначала записал бы его как A, а затем, если бы захотелось повторно использовать вычисления, заставить класс использовать другие вычисления или просто, если код вычисления стал слишком большим, вы могли бы выполнить рефакторинг в класс C

0 голосов
/ 09 марта 2010

Факторизация вычислений, будь то в статическом или глобальном методе, не дает никакой выгоды в отношении осведомленности о состоянии . Единственное небольшое преимущество состоит в том, что код явно показывает, какие из свойств состояния объекта учитываются при расчете (показывать на уровне вызова функции, а не считывать его в логике метода в классе A).

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

  • 1008 * повторное использование *
  • удобочитаемость кода и управление им в целом

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

Квартира лучше вложенной!

.
0 голосов
/ 09 марта 2010

Лично я бы сказал, что это зависит от возможности повторного использования. Если вычисление является тем, которое может использоваться с другими объектами (как это выглядит), то третий пример является наиболее пригодным для повторного использования. Если расчет полностью привязан к объекту или никогда не будет использован повторно, то первый пример. Я бы сказал, что второй пример неверен в большинстве случаев.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...