однострочники пайтон. Однострочники Python лаконичный и содержательный код by Кристи. Однострочники
Скачать 4.44 Mb.
|
38 Глава 1. Краткая памятка по Python Листинг 1.13. Использование ключевого слова continue while True: continue print("43") # недостижимый код Данный код выполняется бесконечно, но оператор print не выполняется ни- когда. Дело в том, что оператор continue завершает текущую итерацию цикла и возвращает поток выполнения в его начало, поэтому print никогда не до- стигается. Подобный никогда не выполняемый код называется недостижимым (dead code). Поэтому оператор continue (как и оператор break ) часто приме- няется при определенных условиях в среде условного выполнения if-else Функции Функции позволяют при необходимости повторно использовать фрагменты кода: писать их один раз, а задействовать многократно. При описании функ- ции указывается ключевое слово def , название функции и набор аргументов для параметризации выполнения ее тела. Различные наборы аргументов могут резко менять возвращаемые функцией результаты. Допустим, вы описали функцию square(x) , возвращающую квадрат входного аргумента x Вызов square(10) возвращает 10 × 10 = 100 , а вызов square(100) возвращает 100 × 100 = 10000 Ключевое слово return завершает выполнение функции и передает поток выполнения вызывающей стороне. Можно также указать необязательное значение после ключевого слова return , содержащее возвращаемый функ- цией результат (листинг 1.14). Листинг 1.14. Ключевое слово return def appreciate(x, percentage): return x + x * percentage / 100 print(appreciate(10000, 5)) # 10500.0 Мы создали функцию appreciate() для вычисления роста вклада при за- данной доходности. В приведенном коде мы вычисляем, насколько растет вклад 10 000 долларов за один год при ставке 5 %. В результате получается 10 500 долларов. С помощью ключевого слова return указываем, что резуль- тат функции должен равняться сумме исходного вклада и номинальной про- центной ставки. Тип возвращаемого значения функции appreciate() — float. Итоги главы 39 Лямбда-функции С помощью ключевого слова lambda в языке Python можно задавать лямбда- функции — анонимные функции, не описанные в пространстве имен. Если не вдаваться в подробности, то это функции без названия, предназначенные для однократного использования. Синтаксис их выглядит так: lambda <аргументы> : <возвращаемое выражение> У лямбда-функции может быть один или несколько аргументов, разделен- ных запятыми. После двоеточия ( : ) описывается возвращаемое выражение, в котором может использоваться (или не использоваться) описанный ранее аргумент. Роль возвращаемого выражения может играть любое выражение или даже другая функция. Лямбда-функции играют важнейшую роль в Python. В коде реальных про- ектов они встречаются повсеместно: например, для сокращения кода или создания аргументов различных функций Python (например, map() или reduce() ). Рассмотрим код в листинге 1.15. Листинг 1.15. Использование ключевого слова lambda print((lambda x: x + 3)(3)) # 6 Сначала мы создаем лямбда-функцию, принимающую на входе значение x и возвращающую результат выражения x + 3 . Результат представляет со- бой объект-функцию, которую можно вызывать точно так же, как любую другую. В соответствии с ее семантикой эту функцию можно назвать функ- цией-инкрементором. Результат ее вызова с аргументом x=3 — суффикс (3) в операторе print в листинге 1.15 — целочисленное значение 6 . В книге мы будем постоянно использовать лямбда-функции, поэтому убедитесь, что хорошо понимаете, как они работают (хотя у вас еще будет возможность тщательнее разобраться в них). Итоги главы В этой главе вы освежили свои знания Python благодаря приведенному краткому экспресс-курсу. Вы посмотрели на важнейшие структуры данных Python и их использование в примерах кода. Научились управлять пото- ком выполнения программы с помощью операторов if-elif-else , а также 40 Глава 1. Краткая памятка по Python циклов for и while . Вы повторили основные типы данных Python — Boolean, integer, float и string — и узнали, какие встраиваемые операции и функции часто применяются для работы с ними. В основе большинства фрагментов кода и нетривиальных алгоритмов на практике лежат обладающие большими возможностями контейнерные типы данных, такие как списки, стеки, мно- жества и ассоциативные массивы. Из приведенных примеров вы научились добавлять, удалять, вставлять и переупорядочивать элементы. Вы также узнали об операторах принадлежности и списковом включении: эффек- тивном и обладающем большими возможностями методе программного создания списков в Python. Наконец, вы узнали о функциях и научились их описывать (включая анонимные лямбда-функции). Теперь вы готовы рассмотреть первые десять простейших однострочников Python. 2 Трюки Python Трюками мы будем называть способы необычайно быстрого или легкого решения задач. В книге вы встретите массу различных трюков и методик повы- шения лаконичности кода, которые к тому же позволят ускорить его реализацию. Хотя приемы Python встре- тятся вам во всех технических главах данной книги, эта по- священа самому очевидному: трюкам, существенно ускоряющим написание кода, которые можно взять на вооружение быстро и без особых усилий. Эта глава также играет роль фундамента для последующих, более продви- нутых глав. Для понимания материала, который будет изложен далее, вам необходимо освоить навыки, заложенные в однострочниках из текущей главы. В частности, мы охватим широкий спектр простейшей функциональ- ности Python, благодаря которой можно писать эффективный код, в том числе списковые включения, доступ к файлам, функции map() и reduce() , лямбда-функции, срезы, присваивание срезам, функции-генераторы и функ- цию zip() Если вы уже опытный программист, то можете пролистать эту главу и ре- шить самостоятельно, какие вопросы хотите изучить подробнее, а в каких уже и так хорошо разбираетесь. 42 Глава 2. Трюки Python Поиск самых высокооплачиваемых работников с помощью спискового включения В данном разделе вы познакомитесь с прекрасной, очень эффективной и по- лезной возможностью Python для создания списков: списковым включением (list comprehension). Оно пригодится нам во множестве однострочников далее в книге. Общее описание Представьте, что вы работаете в отделе кадров большой компании и вам нужно найти всех сотрудников, зарабатывающих по крайней мере 100 000 долларов в год. Выходные результаты должны представлять собой список кортежей, каждый из которых состоит из двух значений: имени сотрудника и его годовой зарплаты. Ниже представлен соответствующий код: employees = {'Alice' : 100000, 'Bob' : 99817, 'Carol' : 122908, 'Frank' : 88123, 'Eve' : 93121} top_earners = [] for key, val in employees.items(): if val >= 100000: top_earners.append((key,val)) print(top_earners) # [('Alice', 100000), ('Carol', 122908)] И хотя код работает правильно, существует более простой и намного более лаконичный, а значит, и удобочитаемый способ получить тот же результат. При прочих равных условиях решение, занимающее меньше строк, будет понятнее для читающего код. В Python существует замечательный способ создания новых списков: спи- сковое включение. Оно описывается простой формулой: [выражение + контекст] Внешние квадратные скобки указывают, что результат представляет собой новый список. Контекст указывает, какие элементы списка необходимо Поиск самых высокооплачиваемых работников с помощью спискового включения 43 взять. Выражение описывает способ модификации элементов списка перед добавлением результата в список. Пример выглядит так: [x * 2 for x in range(3)] Выделенная жирным шрифтом часть, for x in range(3) , представляет со- бой контекст, а остальная часть, x * 2 , — выражение. Выражение удваивает значения 0 , 1 , 2 , сгенерированные контекстом. Таким образом, результат спискового включения представляет собой следующий список: [0, 2, 4] Как выражение, так и контекст могут быть произвольной степени сложно- сти. Выражение может представлять собой функцию от любой описанной в контексте переменной и выполнять любые вычисления — и даже вызывать внешние функции. Задача выражения — модифицировать каждый из эле- ментов списка перед добавлением его в новый список. Контекст может состоять из одной или нескольких переменных, описанных с помощью одного или нескольких вложенных циклов for . Можно также ограничить контекст, задействовав операторы if . В данном случае новое значение добавляется в список только при соблюдении заданного пользо- вателем условия. Списковое включение лучше всего пояснить на примере. Внимательно изу- чите следующие примеры, и вы поймете, что оно собой представляет: print([x for x in range(5)]) # [0, 1, 2, 3, 4] Выражение : тождественная функция (не меняет контекст переменной x ). Контекст : переменная контекста x принимает все значения, возвращаемые функцией range : 0 , 1 , 2 , 3 , 4 print([(x, y) for x in range(3) for y in range(3)]) # [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] Выражение : создает новый кортеж из переменных контекста x и y Контекст : переменная контекста x проходит в цикле по всем значени- ям, возвращаемым функцией range ( 0 , 1 , 2 ); то же делает и переменная контекста y . Эти два цикла for — вложенные, вследствие чего переменная 44 Глава 2. Трюки Python контекста y повторяет итерации своего цикла для каждого из значений переменной контекста x . Таким образом, получается 3 × 3 = 9 сочетаний переменных контекста. print([x ** 2 for x in range(10) if x % 2 > 0]) # [1, 9, 25, 49, 81] Выражение : функция возведения в квадрат переменной контекста x Контекст : переменная контекста x проходит в цикле по всем значениям, возвращаемым функцией range — 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , — но только нечет- ным, то есть когда x % 2 > 0 print([x.lower() for x in ['I', 'AM', 'NOT', 'SHOUTING']]) # ['i', 'am', 'not', 'shouting'] Выражение : строковая функция приведения к нижнему регистру пере- менной контекста x Контекст : переменная контекста x проходит в цикле по всем строковым значениям в списке: 'I' , 'AM' , 'NOT' , 'SHOUTING' Теперь вы сможете понять, что происходит во фрагменте кода, который будет показан ниже. Код Рассмотрим уже обсуждавшуюся ранее задачу с зарплатами сотрудников: по ассоциативному массиву со строковыми ключами и целочисленными значениями создать новый список из кортежей (ключ, значение), таких, что соответствующее ключу значение больше или равно 100 000. Соответству- ющий код приведен в листинге 2.1. Листинг 2.1. Однострочное решение для спискового включения ## Данные employees = {'Alice' : 100000, 'Bob' : 99817, 'Carol' : 122908, 'Frank' : 88123, 'Eve' : 93121} ## Однострочник top_earners = [(k, v) for k, v in employees.items() if v >= 100000] Поиск информативных слов с помощью спискового включения 45 ## Результат print(top_earners) Каковы же будут результаты выполнения этого фрагмента кода? Принцип работы Рассмотрим этот однострочник подробнее. top_earners = [(k, v) for k, v in employees.items() if v >= 100000] Выражение : создает простой кортеж (ключ, значение) для переменных контекста k и v Контекст : метод ассоциативного массива dict.items() обеспечивает проход переменной контекста k в цикле по всем ключам ассоциативного массива, а переменной контекста v — в цикле по соответствующим перемен- ной контекста k значениям, но только если значение переменной контекста v равно или больше 100 000, в соответствии с условием if Результат выполнения этого однострочника выглядит следующим образом: print(top_earners) # [('Alice', 100000), ('Carol', 122908)] В этой простой однострочной программе мы познакомились с важным по- нятием спискового включения. Такие включения используются во многих местах данной книги, поэтому хорошо разберитесь с примерами в текущем разделе, прежде чем читать дальше. Поиск информативных слов с помощью спискового включения В этом однострочнике мы еще более углубимся в изучение обладающей большими возможностями функциональности списковых включений. Общее описание Поисковые системы ранжируют текстовую информацию по степени соот- ветствия запросу пользователя. Для этого поисковые системы анализируют 46 Глава 2. Трюки Python содержимое текста, в котором необходимо произвести поиск. Любой текст состоит из слов. В одних содержится немало информации о содержимом текста, а в других — нет. Примеры первых слов — white, whale, Captain, Ahab 1 (узнали, откуда это?). Примеры слов второго типа — is, to, as, the, a и how, поскольку они содержатся в большинстве текстов. При реализации поис- ковых систем часто отфильтровывают слова, не несущие особого значения. Простейший эвристический подход — отфильтровывать все слова из трех или менее букв. Код Наша цель — решить следующую задачу: создать на основе многострочного строкового значения список списков, каждый из которых состоит из всех слов одной из строк, причем слова эти длиной три символа и более. В ли- стинге 2.2 приведены данные и решение. Листинг 2.2. Однострочное решение для поиска информативных слов ## Данные text = ''' Call me Ishmael. Some years ago - never mind how long precisely - having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen, and regulating the circulation. - Moby Dick''' ## Однострочник w = [[x for x in line.split() if len(x)>3] for line in text.split('\n')] ## Результат print(w) Какими же будут результаты выполнения этого фрагмента кода? Принцип работы Данный однострочник создает список списков с помощью двух вложенных выражений для спискового включения: во внутреннем выражении для спискового включения [x for x in line.split() if len(x)>3] используется строковая функция split() 1 Белый, кит, капитан, Ахав. Чтение файла 47 для разбиения заданной строки на последовательность слов. Мы про- ходим по всем словам x и добавляем в список те из них, длина которых не менее трех символов; во внешнем выражении для спискового включения создается строко- вое значение line , используемое в предыдущем операторе. Опять же, для разбиения текста по символам новой строки '\n' применяется функция split() Конечно, необходимо научиться думать на языке списковых включений, поэтому в первое время они могут показаться сложными. Но когда вы закон- чите читать данную книгу, списковые включения станут для вас обыденными и вы будете быстро писать код на языке Python в подобном стиле. Чтение файла В этом разделе мы прочитаем данные из файла и сохраним результат в виде списка строковых значений (по одному на строку). Мы также удалим из прочитанных строк все ведущие и хвостовые пробельные символы. Общее описание В Python чтение файла не представляет трудности, но требует обычно не- скольких строк кода (и кое-какого поиска в Google). Ниже представлен один из стандартных способов чтения данных из файла в языке Python: filename = "readFileDefault.py" # этот код f = open(filename) lines = [] for line in f: lines.append(line.strip()) print(lines) """ ['filename = "readFileDefault.py" # этот код', '', 'f = open(filename)', 'lines = []', 'for line in f:', 'lines.append(line.strip())', '', 'print(lines)'] """ 48 Глава 2. Трюки Python Предполагается, что этот фрагмент кода сохранен в файле readFileDefault.py в текущем каталоге. Код открывает данный файл, создает пустой список, lines , и заполняет его строковыми значениями с помощью операции append() в теле цикла for , в котором проходит по всем строкам файла. Мы также воспользовались строковым методом strip() для удаления всех ве- дущих и хвостовых пробельных символов (в противном случае в строках бы оказались и символы новой строки '\n' ). Для доступа к файлам на компьютере необходимо знать, как их открывать и закрывать. Получить доступ к файлу данных можно только после его от- крытия. Если файл был закрыт, значит, все данные уже в него записаны. Python может создавать буфер и ожидать некоторое время, пока не запишет весь буфер в файл (рис. 2.1). Причина этого проста: доступ к файлам осу- ществляется довольно медленно. Из соображений эффективности Python не записывает биты по отдельности, а ждет, пока буфер наполнится достаточ- ным количеством байтов, после чего сбрасывает весь буфер в файл целиком. Рис. 2.1. Открытие и закрытие файла на языке Python Именно поэтому рекомендуется с помощью команды f.close() закрывать файл после записи в него данных, чтобы гарантировать, что все данные записаны должным образом, а не остались во временной памяти. Однако существует несколько исключений, когда Python закрывает файл автома- тически, в частности, когда счетчик ссылок уменьшается до нуля, как вы увидите в следующем коде. Код Наша задача: открыть файл, прочитать все строки, удалить ведущие и хво- стовые пробельные символы и сохранить результаты в списке. Соответству- ющий однострочник приведен в листинге 2.3. |