Суть 4 хитроумных концепций Python для новичков

Совсем не просто изучать новый язык программирования, особенно в отсутствии какого-либо опыта в данной сфере. Однако по сравнению с другими языками вам, вероятно, будет легче освоить Python, поскольку для обучения начинающих он предоставляет среду REPL, т. е. цикл “чтение  —  вычисление  —  вывод”. Проще говоря, всё, что вам потребуется,  —  это командная строка. В ней вы пишите код, например print(“Hello, World!”), который она вычисляет и затем в установленном порядке выводит результат. Такой подход обеспечивает обратную связь по разным темам в режиме реального времени, что упрощает процесс изучения Python.

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

1. Виртуальная среда 

Начинающие программисты не поймут всю важность виртуальных сред до тех пор, пока не начнут работать над реальными проектами. Представьте себе такую ситуацию: в одном проекте вы используете конкретный пакет A, который зависит от версии 1.0 пакета X, в другом же вы задействуете пакет B, опирающийся уже на другую версию Х  —  1.5.  

Перед вами встает дилемма: установка версии 1.0 помешает функционированию второго проекта, а версия 1.5 воспрепятствует работе первого. Получается, что для этих проектов нам нужны 2 разных компьютера? Конечно, такой дорогостоящий подход поможет в решении проблемы. А что если у вас несколько разных проектов? В этом случае на лицо вся непрактичность применения отдельных компьютеров.

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

Существуют несколько подходов к управлению виртуальными средами, например venv и conda. Чтобы в этом убедиться, рассмотрим следующий код, иллюстрирующий типичные операции с применением модуля venv, который является частью стандартной библиотеки Python.

  • Для создания виртуальной среды перейдите в нужную директорию и введите python3 -m venv medium-env в инструменте командной строки, например терминале для Mac. Обратите внимание, что medium-env определяет создаваемую вами среду. Также предполагается, что на вашем компьютере уже установлен Python 3. 
  • Создав виртуальную среду, вы можете ее активировать на Mac с помощью следующего кода: source medium-env/bin/activate. Обратите внимание, что для Windows потребуется другая команда
  • С этого момента вы увидите, что строка приглашения к вводу имеет префикс (medium-env), указывающий на то, что вы работаете в виртуальной среде, как и предполагалось. Теперь можно делать все необходимое, например устанавливать новые пакеты. 
  • По мере завершения работы вы можете покинуть виртуальную среду, просто выполнив команду deactivate

Если вы ни разу не работали с виртуальными средами, то процесс их настройки можно упростить за счет установки дистрибутива Anaconda, который позаботится об интерпретаторе Python, управлении пакетами и виртуальной среде. С более подробной информацией вы можете ознакомиться на сайте Anaconda

2. Интерполяция строк (F-строки) 

Нам регулярно приходится подготавливать строки в необходимом формате для их последующего представления. Традиционно такое форматирование осуществляется 2 способами: с помощью функции format и оператора % в стиле C. Рассмотрим несколько простых примеров: 

>>> person = "Danny"
>>> print("Hello, {}!".format(person))
Hello, Danny!
>>> print("Hello, %s!" % person)
Hello, Danny!

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

>>> price = 12.3507
>>> sold_units = 2500
>>> total_cost = price * sold_units
>>> print("The price is ${:.2f}.\nThe # of sold units is {:,}.\nThe total cost is ${:,.2f}.".format(price, sold_units, total_cost))
The price is $12.35.
The # of sold units is 2,500.
The total cost is $30,876.75.

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

>>> price = 12.3507
>>> sold_units = 2500
>>> total_cost = price * sold_units
>>> print(f"The price is ${price:.2f}.\nThe # of sold units is {sold_units:,}.\nThe total cost is ${total_cost:,.2f}.")
The price is $12.35.
The # of sold units is 2,500.
The total cost is $30,876.75.
  • Буква f указывает на то, что мы создаем f-строку. 
  • По аналогии с функцией format f-строки содержат фигурные скобки, обозначающие переменные, которые подлежат интерполяции. 
  • В отличие от функции format каждая интерполяция включает переменную и желаемую вставку, благодаря чему устраняется физическая дистанция между ними, и строки становится легче читать.

3. Отложенное вычисление

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

В первом примере нам понадобятся отложенные атрибуты для экземпляров пользовательского класса. Следующий код демонстрирует реализацию этой функциональности с помощью декоратора property. Для получения аналогичного результата вы также можете поэкспериментировать с декоратором @cached_property модуля functools.

class User:
    def __init__(self, username):
        self.username = username
        self._profile_data = None

    @property
    def profile_data(self):
        if self._profile_data is None:
            # Выполнение дорогостоящей функции веб-запроса 
            fetched_data = get_data_remotely(self.username)
            self._profile_data = fetched_data
        return self._profile_data
  • В методе инициализации, например __init__, мы устанавливаем для защищенного атрибута _profile_data значение None, которое просто выполняет роль плейсхолдера, поскольку в большинстве случаев данные профиля не требуются. 
  • Однако если нам все-таки понадобятся эти данные, то ими можно обернуть декоратор property. Он будет проверять, является ли _profile_data None или нет, и выполнять дорогостоящий веб-запрос только в случае отсутствия данных для атрибута _profile_data

Во втором примере обратимся к генераторам в Python, которые также используют метод отложенных вычислений. Как известно, генераторы —  это особый вид итератора, который отображает элементы по запросу. В отличие от обычных итераторов, созданных из списков и словарей, не все элементы генераторов загружаются в память, что говорит об эффективном ее использовании. Объясняется это тем, что генераторы сохраняют состояние итерации и по мере надобности отображают следующий требуемый элемент. Рассмотрим соответствующий случай использования: 

>>> # Создание списка и вычисление суммы 
>>> simple_list = [x*x for x in range(1000)]
>>> print(f"Size: {simple_list.__sizeof__()} for type: {type(simple_list)}")
Size: 9000 for type: <class 'list'>
>>> print(f"Sum: {sum(simple_list)}")
Sum: 332833500
>>> 
>>> # Создание генератора и вычисление суммы 
>>> simple_gen = (x*x for x in range(1000))
>>> print(f"Size: {simple_gen.__sizeof__()} for type: {type(simple_gen)}")
Size: 96 for type: <class 'generator'>
>>> print(f"Sum: {sum(simple_gen)}")
Sum: 332833500
  • Так называемое выражение-генератор создает простой генератор, который вычисляет квадраты чисел. 
  • По сравнению с объемом, занимаемым списком,  —  9 000 байт, генератор требует лишь малой его части  —  96 байт, при этом оба из них выдают в результате одинаковую сумму. 

4. Генераторы списков, словарей и множеств 

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

>>> # Генератор списка 
>>> squares0 = [x*x for x in range(5)]
>>> print(squares0)
[0, 1, 4, 9, 16]
>>> 
>>> # Цикл for 
>>> squares1 = []
>>> for number in range(5):
...     squares1.append(number*number)
... 
>>> print(squares1)
[0, 1, 4, 9, 16]
  • Синтаксис генератора списка выглядит так: [expression for x in iterable]. В примере выше был использован объект range
  • В качестве альтернативы для итерации объекта range и возведения в квадрат элементов списка можно задействовать цикл for. Однако генератор списков предлагает для этих целей более лаконичный синтаксис и, следовательно, является предпочтительным.

Помимо них, Python также предоставляет генераторы словарей и множеств, представленные ниже: 

>>> # Генератор словаря
>>> squares_dict = {x: x*x for x in range(5)}
>>> print(squares_dict)
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
>>> # Генератор множества 
>>> squares_set = {x*x for x in range(-4, 5)}
>>> print(squares_set)
{0, 1, 4, 9, 16}
  • Синтаксис генератора словаря  —  {key_expr: valu_expr for x in iterable}.
  • Синтаксис генератора множества  —  {expr for x in iterable}.

Заключение 

В данной статье были рассмотрены 4 концепции Python, с пониманием которых у новичков могут возникнуть сложности. Подведем краткие итоги: 

  • Виртуальная среда  —  это способ создания изолированного рабочего пространства для проектов с отличными версиями Python и своими наборами зависимостей.
  • Интерполяция строк, известная в Python как f-строка, является наиболее удобочитаемым способом создания форматированных строк благодаря размещению соответствующей переменной/выражения рядом с применяемыми вставками форматирования. 
  • Отложенное вычисление  —  это метод программирования, позволяющий программе откладывать ресурсозатратные операции, например веб-запрос или сложные вычисления, и выполнять их по требованию. 
  • Метод генераторов предоставляет краткий способ создания списков, словарей и множеств, избавляя от необходимости применения цикла for. 

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Yong Cui: 4 Python Concepts That Beginners May Be Confused About