Цепочка методов — сколько достаточно цепочек методов?

Существуют ли какие-либо рекомендации о том, когда прекратить связывание методов и вместо этого разбить цепочку на несколько выражений?

Рассмотрим, например. этот код Python, который создает словарь со словом в качестве ключа и соответствующим счетчиком в качестве значения:

def build_dict(filename):
    with open(filename, 'r') as f:
        dict = defaultdict(int)

        for word in f.read().lower().split(): # too much?
            dict[word] += 1

        return dict

Можно ли объединить 3 метода? Получу ли я какую-либо заметную выгоду, разделив выражение?


person helpermethod    schedule 28.12.2010    source источник
comment
Придирка. Не назначайте dict, который скрывает встроенный. Возможно, переименуйте его в word_count и переименуйте функцию в count_words. Я не вижу никаких проблем с тремя методами, которые вы связываете. Я могу с первого взгляда сказать, что вы делаете.   -  person Steven Rumbalski    schedule 28.12.2010


Ответы (3)


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

person nmichaels    schedule 28.12.2010

Какой смысл связывать только двоих? Если вы делаете цепочку методов, делайте это правильно.

Это больше проблема форматирования, если для одной строки это слишком много, я предпочитаю

(x.Foo()
  .Bar()
  .FooBar()
  .Barf());

Другой проблемой могут быть отладчики, которые заставляют вас выполнять трассировку в Foo, если вы хотите трассировать в Bar.

person peterchen    schedule 28.12.2010
comment
о! Вы правы, конечно. Есть ли альтернатива длинным цепочкам, которая работает на питоне? (Мой единственный опыт работы с python — это возиться со сценариями сборки и надеяться, что я не сильно сломаюсь) - person peterchen; 28.12.2010
comment
Поместите круглые скобки вокруг всего выражения, и оно будет работать нормально. - person Duncan; 28.12.2010

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

Если вы уверены, что исключения не произойдет, то

for word in f.read().lower().split():
    dict[word] += 1

может быть предпочтительнее

contents=f.read()
contents=contents.lower()
words=contents.split()
for word in words:
    d[word] += 1

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

Если память не является проблемой и, в частности, если words или contents можно будет снова использовать позже в коде, то назначение переменной для ссылки на них, конечно, будет быстрее, поскольку методы read, lower и/или split не должны быть снова позвонил.

person unutbu    schedule 28.12.2010
comment
Я думаю, что память не является проблемой, поскольку стандартная реализация подсчитывает ссылки. - person Xavier Combelle; 28.12.2010
comment
Да, но область действия уже, когда они изменены, и gc может очистить объекты раньше. - person Falmarri; 28.12.2010