Дэвид бизли python исчерпывающее руководство

Разнообразие возможностей современного Python становится испытанием для разработчиков всех уровней. Как программисту на старте карьеры понять, с чего начать, чтобы это испытание не стало для него непосильным? Как опытному разработчику Python понять, эффективен или нет его стиль программирования? Как перейти от изучения отдельных возможностей к мышлению на Python на более глубоком уровне? «Python. Исчерпывающее руководство» отвечает на эти, а также на многие другие актуальные вопросы.
Эта книга делает акцент на основополагающих возможностях Python (3.6 и выше), а примеры кода демонстрируют «механику» языка и учат структурировать программы, чтобы их было проще читать, тестировать и отлаживать. Дэвид Бизли знакомит нас со своим уникальным взглядом на то, как на самом деле работает этот язык программирования.
Перед вами практическое руководство, в котором компактно изложены такие фундаментальные темы программирования, как абстракции данных, управление программной логикой, структура программ, функции, объекты и модули, лежащие в основе проектов Python любого масштаба.

2023 г., мягкая обложка, 368 страниц, 580 г

код 2949409, тираж 1700 экз.

Перейти к характеристикам

Время на прочтение
8 мин

Количество просмотров 15K

imageПривет, Хаброжители.
По плану у нас руководство по Python.

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

Эта книга делает акцент на основополагающих возможностях Python (3.6 и выше), а примеры кода демонстрируют «механику» языка и учат структурировать программы, чтобы их было проще читать, тестировать и отлаживать. Дэвид Бизли знакомит нас со своим уникальным взглядом на то, как на самом деле работает этот язык программирования.

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

5.16. ПЕРЕДАЧА АРГУМЕНТОВ ФУНКЦИЯМ ОБРАТНОГО ВЫЗОВА

Одна серьезная проблема с функциями обратного вызова связана с передачей аргументов передаваемой функции. Возьмем написанную ранее функцию after():

import time

def after(seconds, func):
     time.sleep(seconds)
     func()

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

def add(x, y):
     print(f'{x} + {y} -> {x+y}')
     return x + y

after(10, add(2, 3)) # Ошибка: add() вызывается немедленно

Здесь функция add(2, 3) выполняется немедленно, возвращая 5. Потом after() вызывает ошибку, пытаясь выполнить 5(). Это определенно не то, чего вы ожидали. Но на первый взгляд нет очевидного способа заставить программу работать при вызове add() с нужными аргументами.

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

В нашем случае одно из возможных решений основано на упаковке вычисления в функцию с нулем аргументов при помощи lambda:

after(10, lambda: add(2, 3))

Такие маленькие функции с нулем аргументов иногда называют преобразователями (thunk). Это выражение, которое будет вычислено позднее, когда будет вызвано как функция с нулем аргументов. Этот способ может стать приемом общего назначения, позволяющим отложить вычисление любого выражения на будущее. Поместите выражение в lambda и вызовите функцию, когда вам понадобится значение.

Вместо использования лямбда-функции можно воспользоваться вызовом functools.partial() для создания частично вычисленной функции:

from functools import partial

after(10, partial(add, 2, 3))

partial() создает вызываемый объект, один или несколько аргументов которого уже были заданы и кешированы. Это может быть удобным способом привести неподходящие функции в соответствие с ожидаемыми сигнатурами в обратных вызовах и других возможных применениях. Несколько примеров использования partial():

def func(a, b, c, d):
     print(a, b, c, d)

f = partial(func, 1, 2)          # Зафиксировать a=1, b=2
f(3, 4) # func(1, 2, 3, 4)
f(10, 20) # func(1, 2, 10, 20)

g = partial(func, 1, 2, d=4)     # Зафиксировать a=1, b=2, d=4
g(3) # func(1, 2, 3, 4)
g(10) # func(1, 2, 10, 4)

partial() и lambda могут использоваться для похожих целей. Но между этими двумя решениями есть важные семантические различия. С partial() вычисление и связывание аргументов происходит при первом определении частичной функции. При использовании лямбда-функции с нулем аргументов вычисление и связывание аргументов выполняется во время фактического выполнения лямбда-функции (все вычисления откладываются):

>>> def func(x, y):
... return x + y
...
>>> a = 2
>>> b = 3
>>> f = lambda: func(a, b)
>>> g = partial(func, a, b)
>>> a = 10
>>> b = 20
>>> f() # Использует текущие значения a, b
30
>>> g() # Использует текущие значения a, b
5
>>>

Частичные выражения вычисляются полностью, поэтому вызов partial() создает объекты, способные сериализоваться в последовательности байтов, сохраняться в файлах и даже передаваться по сети (например, средствами модуля стандартной библиотеки pickle). С лямбда-функциями это невозможно. Поэтому в приложениях с передачей функций (возможно, с интерпретаторами Python, работающими в разных процессах или на разных компьютерах) решение c partial() оказывается более гибким.

Замечу, что применение частичных функций тесно связано с концепцией, называемой каррированием (currying). Это прием функционального программирования, где функция с несколькими аргументами выражается цепочкой вложенных функций с одним аргументом:

# Функция с тремя аргументами
def f(x, y, z):
     return x + y + z

# Каррированная версия
def fc(x):
     return lambda y: (lambda z: x + y + z)

# Пример использования
a = f(2, 3, 4)      # Функция с тремя аргументами
b = fc(2)(3)(4)     # Каррированная версия

Этот прием не относится к общепринятому стилю программирования Python, и причины для его практического применения встречаются редко. Но иногда слово «каррирование» мелькает в разговорах с программистами, которые провели много времени, разбираясь в таких вещах, как лямбда-счисление. Этот метод обработки нескольких аргументов был назван в честь знаменитого логика Хаскелла Карри. Полезно знать, что это такое, например, если вы столкнетесь с группой функциональных программистов, ожесточенно спорящих на каком-нибудь светском мероприятии.

Вернемся к исходной проблеме передачи аргументов. Другой вариант передачи аргументов функции обратного вызова основан на их передаче в отдельных аргументах внешней вызывающей функции. Рассмотрим следующую версию функции after():

def after(seconds, func, *args):
     time.sleep(seconds)
     func(*args)

after(10, add, 2, 3) # Вызывает add(2, 3) через 10 секунд

Заметьте, что передача ключевых аргументов func() не поддерживается. Это было сделано намеренно. Одна из проблем ключевых аргументов в том, что имена аргументов заданной функции могут конфликтовать с уже используемыми именами (то есть seconds и func). Ключевые аргументы могут быть зарезервированы для передачи параметров самой функции after():

def after(seconds, func, *args, debug=False):
     time.sleep(seconds)
     if debug:
          print('About to call', func, args)
func(*args)

Но не все потеряно. Задать ключевые аргументы для func() можно при помощи partial():

after(10, partial(add, y=3), 2)

Если вы хотите, чтобы функция after() получала ключевые аргументы, безопасным решением может стать использование только позиционных аргументов:

def after(seconds, func, debug=False, /, *args, **kwargs):
     time.sleep(seconds)
     if debug:
          print('About to call', func, args, kwargs)
     func(*args, **kwargs)

after(10, add, 2, y=3)

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

def after(seconds, func, debug=False):
     def call(*args, **kwargs):
          time.sleep(seconds)
          if debug:
               print('About to call', func, args, kwargs)
          func(*args, **kwargs)
     return call

after(10, add)(2, y=3)

Теперь конфликты между аргументами after() и func полностью исключены. Но такие решения могут породить конфликты с вашими коллегами, которые будут читать ваш код.

5.17. ВОЗВРАЩЕНИЕ РЕЗУЛЬТАТОВ ИЗ ОБРАТНЫХ ВЫЗОВОВ

В прошлом разделе не упоминалась еще одна проблема: возвращение результатов вычислений. Рассмотрим измененную функцию after():

def after(seconds, func, *args):
     time.sleep(seconds)
     return func(*args)

Она работает, но есть неочевидные граничные случаи, возникающие из-за того, что в ней задействованы две разные функции: сама функция after() и переданный обратный вызов func.
Одна из сложностей связана с обработкой исключений. Опробуйте следующие два примера:

after("1", add, 2, 3)            # Ошибка: TypeError (ожидается целое число)
after(1, add, "2", 3)            # Ошибка: TypeError (конкатенация int
                                 # со str невозможна)

В обоих случаях выдается ошибка TypeError, но по разным причинам и в разных функциях. Первая ошибка обусловлена проблемой в самой функции after(): функции time.sleep() передается неправильный аргумент. Вторая ошибка возникает из-за проблемы с выполнением функции обратного вызова func(*args).

Есть несколько вариантов, чтобы различить эти два случая. В одном из них используются цепочки исключений. Идея в том, чтобы упаковать ошибки из обратного вызова особым способом, позволяющим обрабатывать их отдельно от других ошибок:

class CallbackError(Exception):
     pass

def after(seconds, func, *args):
     time.sleep(seconds)
     try:
          return func(*args)
     except Exception as err:
          raise CallbackError('Callback function failed') from err

Измененный код отделяет ошибки от переданного обратного вызова в отдельную категорию исключений. Он используется примерно так:

try:
     r = after(delay, add, x, y)
except CallbackError as err:
     print("It failed. Reason", err.__cause__)

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

Вся эта схема неочевидна. Но на практике обработка ошибок — достаточно сложная тема. Такой подход позволяет точнее управлять распределением ответственности и упрощает документирование поведения after(). Если с обратным вызовом возникают проблемы, программа всегда сообщает о ней в виде CallbackError.

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

class Result:
     def __init__(self, value=None, exc=None):
          self._value = value
          self._exc = exc
     def result(self):
          if self._exc:
               raise self._exc
          else:
               return self._value

Далее используйте этот класс для возвращения результатов из функции after():

def after(seconds, func, *args):
     time.sleep(seconds)
     try:
          return Result(value=func(*args))
     except Exception as err:
          return Result(exc=err)

# Пример использования:

r = after(1, add, 2, 3)
print(r.result())              # Выводит 5
s = after("1", add, 2, 3)      # Немедленно выдает TypeError -
                               # недопустимый аргумент sleep().

t = after(1, add, "2", 3)      # Возвращает "Result"
print(t.result())              # Выдает TypeError

Второй способ основан на выделении выдачи результата функции обратного вызова в отдельный шаг. При возникновении проблемы с after() о ней будет сообщено немедленно. Если возникнет проблема с обратным вызовом func(), уведомление о ней будет отправлено при попытке пользователя получить результат вызовом метода result().

Этот стиль упаковки результата в специальный экземпляр для распаковки в будущем все чаще встречается в современных языках программирования. Одна из причин в том, что он упрощает проверку типов. Если вам понадобится включить аннотацию типа в after(), ее поведение полностью определено — она всегда возвращает Result и ничего другого:

def after(seconds, func, *args) -> Result:
     ...

Этот паттерн еще не так часто встречается в коде Python, но он регулярно возникает при работе с примитивами синхронизации (потоками и процессами). Например, экземпляры Future ведут себя так при работе с пулами потоков:

from concurrent.futures import ThreadPoolExecutor

pool = ThreadPoolExecutor(16)
r = pool.submit(add, 2, 3)            # Возвращает Future
print(r.result())                     # Распаковывает результат Future

Об авторе

Дэвид Бизли — автор книг Python Essential Reference, 4-е издание (Addison-Wesley, 2010) и Python Cookbook, 3-е издание (O’Reilly, 2013). Сейчас ведет учебные курсы повышения квалификации в своей компании Dabeaz LLC (www.dabeaz.com). Он пишет на Python и преподает его с 1996 года.

Более подробно с книгой можно ознакомиться на сайте издательства:
» Оглавление
» Отрывок

По факту оплаты бумажной версии книги на e-mail высылается электронная книга.
Для Хаброжителей скидка 25% по купону — Python

Краткая рецензия

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

Не подойдет для новичков, так как темы, которые рассматриваются в книге сложные и требуют хорошей подготовки.

Полная рецензия

Продолжаем обзор книг по питону и сегодня у меня в руках «Python — исчерпывающее руководство» Дэвида Бизли.

Давайте сразу посмотрим на обратную строну обложки и всё, что тут написано выглядит очень вкусно. Если вы новичок в Python, то мало что здесь поймете.

Тем не менее вы можете сказать что-то вроде: «Фундаментальные средства Python — то, что надо», «Невероятная мощь генераторов, звучит как минимум круто», «Эффективные операции с данными и анализ задач — да, я точно стану отличным Python разработчиком, надо брать!»

Однако самое главное, что вы скорее всего пропустите или не придадите вниманию — это надпись на лицевой стороне — »Для практикующих программистов». И это самое важное, что нужно знать про эту книгу.

Для практикующих программистов

Для практикующих программистов.

Она не для новичков, она для реальных разработчиков, которые пишут python-код в данный момент и которые хотят стать круче. Начинающим программистам данная «Python — Исчерпывающее руководство» будет непонятна и сложна.

И уже в первой главе Дэвид Бизли приводит примеры циклов, условий, методов, менеджеров контекста, списков, словарей, множеств, функций, исключений, объектов, модулей, классов, пакетов, а также использует моржовый оператор. То есть уже к 56 странице мы познакомились со всеми синтаксическими конструкциями языка. В «Python для чайников» мы первую программу написали только после сотой страницы, а тут уже в первой главе приводится более 100 примеров с использованием всего арсенала языка.

Изначально я подумал, что данная книга похожа на «Python. Экспресс-курс» Наоми Седдер, «Python 3. Самое необходимое» Дронова и Прохоренка или «Простой Python» Билла Любановича.

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

И полезность задач распространялась далеко за пределы Python. Это могли быть и примеры работы с базами данных, и обработка excel-файлов, и получение информации с помощью сетевых протоколов.

Тут же всё немного по-другому, да автор приводит много примеров, но практически все они сконцентрированы в области возможностей самого Python.

Поэтому «Исчерпывающее руководство» логичней сравнить с «Чистым Python» Дэна Бейдера или даже с «Изучаем Python» Марка Лутца. Если выбросить из Лутца всё лишнее и ужать два тома до какой-то краткой выжимки, то мы получим что-то вроде Исчерпывающего руководства Дэвида Бизли.

Собственно, даже по-английски книга называется Python Distilled — дистиллированный Питон. А дистиллированный — это значит очищенный, от всяких примесей.

Но, давайте посмотрим, что нас ждет после первой главы.

Краткое содержание книги

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

В третьей главе, посвященной управлению потоком выполнения программы вы, разумеется, поближе познакомитесь с условиями и циклами, включая вот такую распаковку внутри for:

Распаковка внутри for

Распаковка внутри forв.

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

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

Мы такие штуки у себя на сайте перехватываем и это та еще головная боль.

4 глава посвящена объектам, типам данных и протоколам. Именно тут вы познакомитесь с дробями, массивами из библиотеки NumPy, а также типом Decimal. Причем именно познакомитесь, без какого сложного погружения. Вот вам один пример с дробями, вот один пример с массивом, нужно больше — вперед в документацию.

Далее вы еще сильнее углубитесь в менеджеры контекста, а также в логирование и отладку программ. Эти темы тоже не для новичков.

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

Список магических методов

Список магических методов.

В 5 главе вы расширите свое понимание работы функций, включая аннотации, рекурсию, лямда-функции, колбэки, декораторы, а также элементы функционального программирования: map, reduce и всё такое. И объяснений здесь также минимум: описание, несколько примеров, дальше сами.

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

Далее мы переходим к созданию генераторов, а после к классам и объектно-ориентированному программированию.

Я посмотрел несколько примеров, почитал к ним описание и мне понравилось. Всё лаконично и без воды, автор явно разбирается в том, что пишет, то есть в Python. В Исчерпвающем руководстве много интересных ходов, полезных примеров, а также есть пища для размышлений.

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

Повторюсь, что новичку это всё вообще не нужно, но если вы метите на мидла или даже сеньора, то такие вещи знать обязательно. На собесе можно на них легко нарваться.

8 глава посвящена модулям и пакетам, а девятую (последнюю) можно разбить на две части. Первая про работу с файлами, а затем идет описание модулей из стандартной библиотеки Python. Некоторым модулям посвящено всего по полстранички, но пробежаться по ним будет полезно.

Итоги

Что ж, настало время выводов и данная книга мне понравилась. Она не тривиальная и достаточно глубокая. Если вы хотите развиваться именно как Python разработчик, то я рекомендую её прочесть. Она мне понравилась даже больше, чем Чистый Python Дэна Бэйдера. В целом они чем-то похожи, но Дэвид Бизли несколько глубже. Впрочем, я рекомендую прочитать обе этих книги, они хорошо друг друга дополняют и для решения одних и тех же задач нередко используют разные подходы.

Кстати, обе эти книги издательства Питер, и для тех моих дорогих зрителей, кто хочет купить книги на сайте издательства, у меня есть промокод на скидку, оставлю его под видео.

На этом у меня всё, пока и успехов в учебе!

 Вернуться

Автор: Бизли Д.
Дата выхода: 2023
Издательство: Издательский дом «Питер»
Количество страниц: 368

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

 Эта книга делает акцент на основополагающих возможностях Python (3.6 и выше), а примеры кода демонстрируют «механику» языка и учат структурировать программы, чтобы их было проще читать, тестировать и отлаживать. Дэвид Бизли знакомит нас со своим уникальным взглядом на то, как на самом деле работает этот язык программирования.

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

Если вам понравилась эта книга поделитесь ею с друзьями, тем самым вы помогаете нам
развиваться и добавлять всё больше интересных и нужным вам книг!

Python. Исчерпывающее руководство

Название: Python. Исчерпывающее руководство
Автор: Дэвид Бизли
Год: 2023
Издательство: СПб.: Питер
Язык: русский
Формат: pdf
Страниц: 368
Размер: 5.6 Мб

Эта книга делает акцент на основополагающих возможностях Python, а примеры кода демонстрируют механику языка и учат структурировать программы.

Краткое содержание:

  • Основы Python
  • Операторы, выражения и обработка данных
  • Структура программы и управление последовательностью выполнения
  • Объекты, типы и протоколы
  • Функции
  • Генераторы
  • Классы и объектно-ориентированное программирование
  • Модули и пакеты
  • Ввод/вывод
  • Встроенные функции и стандартная библиотека

Скачать Дэвид Бизли. Python. Исчерпывающее руководство

Понравилась статья? Поделить с друзьями:
  • Hp laserjet p1102 инструкция по разборке
  • Руководство по охране труда для работодателя
  • Приставка для цифрового телевидения люмакс инструкция
  • Ангидакт спрей для горла инструкция по применению взрослым цена
  • Кардиопассит инструкция по применению отзывы кардиопасит настойка