Be Pythonic

http://www.cafepy.com/article/be_pythonic/
  • Перевод

От переводчика


Представляю вашему внимаю перевод статьи Shalabh Chaturvedi «Be Pythonic», рекомендованной в этом топике. Если мое начинание будет поддержано, планирую также перевести две остальные упомянутые там статьи этого автора.

Вступление


Эта статья предназначена для новичков в Python.

При переходе с одного языка на другой некоторые вещи для вас могут остаться неизвестными (см. Transfer of Learning). То, что вам известно о других языках, может быть не всегда полезным в Python. Эта статья содержит некоторые используемые в Python идиомы, которые мне особенно нравятся. Я надеюсь, читатели найдут их полезными для овладения языком.


Счетчики нужны редко, итераторы — лишь иногда


Неправильно:
i = 0
while i<10:
   do_something(i)
   i += 1

Правильно:
for i in xrange(10):
  do_something(i)

В следующем примере программа проходит по списку.
Неправильно:
i = 0
while i<len(L):
  do_something(L[i])
  i += 1

Правильно:
for item in L:
  do_something(item)

Итераторы полезны, когда вы хотите сохранить позицию в цикле между двумя запусками:
itrL = iter(L)

for item in itrL:
  do_something(item)
  if is_some_condition(item):
    break

for item in itrL:  # продолжаем с места, на котором мы вышли из предыдущего цикла
  do_something_else(item)

Может быть, вам не нужен цикл for


Python предоставляет много средств более высокого уровня для работы с последовательностями, например, zip(), max(), min(), list comprehensions (генерация списков), generator expressions (компактная запись генераторов) и т. д. Эти и другие функции описаны в разделе «Built-in Functions» документации.

Вы можете хранить данные в кортежах, списках, словарях и работать с целыми наборами. Например, вот пример кода, который читает CSV-файл (в котором первая строка содержит названия полей), преобразует каждую строку в элемент словаря и считает сумму чисел в столбце «quantity».
f = open('filename.csv')              # f — итератор
field_names = f.next().split(',')     # берем первый элемент итератора с помощью next()
records = [dict(zip(field_names, line.split(','))) for line in f] # получаем оставшиеся строки
print sum(int(record['quantity']) for record in records)

В любом случае вы должны использовать модуль csv, входящий в Python Standard Library, но этот пример иллюстрирует некоторые полезные особенности. Используя zip() и dict(), вы можете объединить кортеж названий и кортеж значений и получить словарь. А в сочетании с генерацией списков вы можете сделать это с целым списком за один шаг.

Кортеж — это не список, который нельзя редактировать


Содержимое кортежа обычно разнородно, например, (first_name, last_name) или (ip_address, port). При этом тип данных может быть одинаковым (и first_name, и last_name — строки). Вы можете думать о кортеже как о строке в реляционной базе данных — фактически строка таблицы даже называется кортежем в формальном описании реляционной модели. Напротив, список имен — это всегда список.

Распаковка кортежей — это полезный способ для извлечения элементов из них. Например:
for (ip_address, port) in all_connections:
  if port<2000:
    print 'Connected to %s on %s' % (ip_address, port)

Этот код показывает, что all_connections — это список (или iterable объект), содержащий кортежи вида (ip_address, port). Это лучше, чем использовать for item in all_connections и вызывать элемент через item[0] или похожим способом.
Также стоит использовать распаковку кортежей, если функция должна возвращать несколько значений:
# разделяем имя файла на основную часть и расширение
name, ext = os.path.splitext(filename)  

Классы предназначены не для группировки функций


C# и Java позволяют размещать код только в классах, поэтому в них много служебных классов, содержащих только статические методы. Например, это математические функции, такие как sin(). В Python вы просто используете модуль, содержащий функции верхнего уровня.

Скажите «нет» геттерам и сеттерам


Да, инкапсуляция важна. Но геттеры и сеттеры — не единственный способ для этого. В Python вы можете использовать property вместо членов класса, то есть полностью изменить способ инкапсуляции без изменения кода, использующего класс.

Функции — это объекты


Функция — это объект, который можно вызвать. Этот пример сортирует список словарей по значению, соответствующему ключу 'price':
# определяем функцию, возвращающую полезные данные из объекта
def get_price(ob):
  return ob['price']

L.sort(key=get_price)  # сортируем список, используя значение ['price'] объектов в списке

* This source code was highlighted with Source Code Highlighter.

Вы также можете использовать sorted(L, key=get_price), чтобы получить новый список вместо изменения имеющегося.

Ссылки по теме


Python is not Java
What is Pythonic
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 57
  • +5
    Спасибо, очень интересно!
    • +5
      Спасибо, очень интересно!
      • +5
        Спасибо, очень интересно!
        • +4
          Спасибо, очень интересно!
          • +4
            Спасибо, очень интересно!
            • +20
              C-C-C-COMBO BREAKER!
              • +6
                Перечитал 3 раза, захватывающее чтиво.
                • +5
                  Очень интересно, спасибо!
                  • НЛО прилетело и опубликовало эту надпись здесь
                    • НЛО прилетело и опубликовало эту надпись здесь
                    • 0
                      Даешь синусоиду в комментариях :)
                    • НЛО прилетело и опубликовало эту надпись здесь
                      • –3
                        Спасибо, очень интересно!
                        • –3
                          Спасибо, очень интересно!
                          • –1
                            Ээээ… За что заминусовали человека?
                            • НЛО прилетело и опубликовало эту надпись здесь
                          • –2
                            Спасибо, очень интересно!
                          • 0
                            Спасибо, очень интересно!
                      • +5
                        Эхх, как мне не хватало подобной статьи когда я начинал знакомиться с Питоном.
                        Однозначно продолжать!
                        • +3
                          Действительно, куча вот таких вот особенностей может остаться за бортом, если изучаешь Python после C, Java или подобных. Как чуть было не получилось у меня.

                          Обязательно продолжайте.
                          • 0
                            Я конечно извиняюсь, но вся эта информация содержится в официальном tutorial. Или вы начинали знакомиться с питоном в обход официальной документации?
                          • +3
                            Жду дальнейших переводов :)
                            • +1
                              иногда очень помогает перечитать туториалы и whats new.
                              Я больше года делал вот так, когда нужно было пройтись по всех элементам списка с их нумерацией:
                              i=0
                              for x in some_list:
                              print i,x
                              i+=1
                              хотя можно было обойтись функцией enumerate, на которую я наткнулся в whats new какой то версии питона, в более старых учебниках соответственно этого не было
                              for i,x in enumerate(some_list):
                              print i,x
                              • +2
                                Когда у меня возникла такая же задача, я первым делом погуглил, потому что был уверен, что в таком красивом языке должен быть красивый способ.
                                • +1
                                  я когда сам написал, потому что не знал, что есть готовое
                                  def enumerate(some_list):
                                    return zip(range(len(some_list), some_list)
                                  
                                • НЛО прилетело и опубликовало эту надпись здесь
                                  • +2
                                    К счастью, это можно понять из следующего предложения. А заголовок призывает не смешивать понятия кортежа и списка.
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                      • +1
                                        Здесь есть тонкость. Кортеж — это список (в полном смысле этого русского слова), но не list (понимаемый как тип данных).
                                    • +1
                                      Кстати, что значит «неизменяемый» применительно к кортежу — тоже не все понимают. И уверены, что код

                                      x = 1,2,3
                                      x += 4,5

                                      работать не будет.

                                      Ну и могут вообще не понять, что тут с кортежами идет работа, особенно если помнят «операцию запятая» в Си и применяют свои знания в питоне.
                                    • –5
                                      очень интересно, хотелось бы еще примеры для переходящих с Пых-Пыха
                                      • 0
                                        ножно купить книжку, говорят, чтение помогает получить новые знания, не дожидаясь «еще примеров» ;)
                                      • –3
                                        Здорово, но про «Кортеж — это не список, который нельзя редактировать» не согласен, т.к. в разделе показан пример, который будет работать и со списком, который также можно распаоквывать. Так что лично для меня, tuple по-прежнему остается списком, который нельзя редактировать.

                                        Если я чего-то не знаю, расскажите, пожалуйста.
                                        • +2
                                          Упс, это я поторопился. Да, пример верный.
                                        • +8
                                          Хм, а я ничего нового не прочел. Видимо я не так плохо знаю Python. Спасибо за поднятие ЧСВ=)
                                          • +1
                                            «Этот пример сортирует список словарей по значению, соответствующему ключу 'key'»
                                            Видимо, должно быть: «соответствующему ключу 'price'»
                                          • +1
                                            Ждем продолжение.
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                              • +2
                                                К хорошему привыкаешь быстро ;-)
                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                  • +4
                                                    Да. После питона на php писать становится грустно.
                                                    • +1
                                                      После питона писать надо на питоне, а не на php
                                                      • +2
                                                        Для себя я теперь на php не пишу. Для заказчиков, увы, приходится.
                                                  • +2
                                                    кстати в питоне и JS есть очень много общего… на первый взгяд не так заметно, но изнутри очень родные
                                                    • 0
                                                      Ну, Python на Javascript довольно-таки похож. Я за месяц примерно освоился, даже меньше
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                    • +3
                                                      Большое спасибо за статью. Недавно публиковал тут код на Питоне. Пришлось провести немало времени, выясняя, что есть pythonic, а что не очень. Такого рода статьи в тот момент я не нашел. А жаль — очень бы пригодилась.

                                                      Думаю такие публикации были бы полезны и по другим языкам, потому что осваивая что-то новое часто бывает очень не просто отказаться от привычек программирования на «родном» языке. А надо. 8)
                                                      • +1
                                                        Прочитал про парсинг csv файла и хочу сказать, что это просто охуительно!
                                                        Не зря я осваиваю Джангу. Питон — потрясающий язык. Позади — basic)), pascal, asp, perl, php, вот пришел к Питону. Дальше хочу за плюсы.

                                                        Питон, я иду! :)
                                                        • +1
                                                          Не пугайте его так, он хороший.
                                                          • +1
                                                            Я тоже хороший :)
                                                        • +4
                                                          Хорошие советы, кроме «Скажите «нет» геттерам и сеттерам». Использование property может легко сделаеть код не проще и понятнее, а скорее наоборот, запутаннее и «магичнее».

                                                          Раздел «функции — это объекты» был бы отличной демонстрацией того, где в питоне стоит применять лямбда-функции:

                                                          L.sort(key=lambda item: item['price'])

                                                          • +2
                                                            а, ну и название переменной L не по pep-8 :)
                                                          • +2
                                                            Про выполнение кучи всего в одной строке — не самый удачный пример у изначального автора.

                                                            Такие строки не сходу понимаешь и вероятность багов в них растёт, как комменты «Спасибо, понравилось!» в вверху.

                                                            Т.е. концепция вроде правильная, но пример для культуры писания не удачен. Писать надо понятно, ибо мы большую часть времени код читаем.
                                                            • 0
                                                              С моей точки зрения, если знать эти приемы, то читаемость повысится. Это же строки не в 400 символов длиной
                                                              • 0
                                                                Дык не все же мы знаем — есть старшие программеры, а есть просто программеры.

                                                                А код д.б. понимаем всеми как минимум, пусть даже талант к его созданию есть тока у страших товарищей.

                                                                Т.е. я лично болею за читаемость. Либо такие заносы в отдельные функции/методы выкидывать.
                                                            • 0
                                                              Главное так и не было сказано — для цикла for есть конструкция:

                                                              for i, item in enumerate(mylist):
                                                                  pass

                                                              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.