LINUX.ORG.RU

Python 3.7

 ,


4

8

Спустя полтора года после выхода предыдущей мажорной версии, наконец-то состоялся релиз Python 3.7.

В этом выпуске

  • Улучшена поддержка аннотации типов
  • Data classes
  • Атрибуты модулей
  • Отладка с помощью breakpoint()
  • И многое другое

PEP 563, Отложенное исполнение аннотаций типов

Теперь аннотации разрешаются в момент вызова функции, а не в момент загрузки её кода. Это уменьшает время старта программы и делает доступным использование имён, определённых позднее самой функции (forward references).

Такой код вызывал бы ошибку в предыдущих версиях Python

class C:
    @classmethod
    def from_string(cls, source: str) -> C:
        ...

    def validate_b(self, obj: B) -> bool:
        ...

class B:
    ...

Это изменение нарушает совместимость, поэтому до прихода версии Python 4.0 пока требует

from __future__ import annotations

PEP 553, Встроенная функция breakpoint()

Отладка стала ещё проще! Допустим, у вас есть такой код

def divide(e, f):
    return f / e

a, b = 0, 1
print(divide(a, b))

В предыдущих версиях для отладки вам требовалось:

def divide(e, f):
    import pdb; pdb.set_trace()
    return f / e

В 3.7 это выглядит проще и короче

def divide(e, f):
    breakpoint()
    return f / e

Теперь запускайте ваш код:

$ python3.7 bugs.py 
> /home/gahjelle/bugs.py(3)divide()
-> return f / e
(Pdb)

По умолчанию breakpoint() просто заменяется на import pdb; pdb.set_trace(), однако это можно изменить. Скажем, вы можете использовать другой отладчик:

$ PYTHONBREAKPOINT=pudb.set_trace python3.7 bugs.py
Или отключить отладку вовсе
$ PYTHONBREAKPOINT=0 python3.7 bugs.py
ZeroDivisionError: division by zero
Или запустить IPython
$ PYTHONBREAKPOINT=IPython.embed python3.7 bugs.py 
IPython 6.3.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: print(e / f)
0.0
В конечном счёте, вы можете написать свой собственный обработчик breakpoint()

PEP 557, Data Classes

Новый модуль dataclasses делает более удобным написание классов, основная задача которых — хранить данные. Вы просто используете декоратор, и весь бойлерплейт пишется за вас.

from dataclasses import dataclass, field

@dataclass(order=True)
class Country:
    name: str
    population: int
    area: float = field(repr=False, compare=False)
    coastline: float = 0

    def beach_per_person(self):
        """Meters of coastline per person"""
        return (self.coastline * 1000) / self.population

Методы __init__, __repr__, __eq__, __ne__, __lt__, __le__, __gt__, __ge__ будут сгенерированы автоматически для класса Country

PEP 562, Кастомизация атрибутов модулей

Вы уже давно знакомы с __getattr__ для классов. Теперь этот метод может быть определён и для модулей. Типичные примеры использования: сообщить о том, что некоторая функция в модуле объявлена deprecated, а также ленивая загрузка тяжелых подмодулей.

PEP 564, Временны́е функции с наносекундным разрешением

Улучшен модуль time, добавлено несколько новых функций

time.clock_gettime_ns()
time.clock_settime_ns()
time.monotonic_ns()
time.perf_counter_ns()
time.process_time_ns()
time.time_ns()
Точность расчёта временных интервалов повышена до наносекунд

Упорядоченные словари

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

>>> {"one": 1, "two": 2, "three": 3}  # Python <= 3.5
{'three': 3, 'one': 1, 'two': 2}

>>> {"one": 1, "two": 2, "three": 3}  # Python >= 3.6
{'one': 1, 'two': 2, 'three': 3}

Это работало ещё с версии 3.6, однако опиралось на внутреннюю реализацию словарей CPython, и полагаться на такой порядок было нельзя.

Новые ключевые слова: async и await

Корутины с async и await были введены в Python 3.5, однако для обратной совмесимости всё ещё можно было объявить переменные с такими именами. Теперь это будет выдавать ошибку.

>>> async = 1
  File "<stdin>", line 1
    async = 1
          ^
SyntaxError: invalid syntax

>>> def await():
  File "<stdin>", line 1
    def await():
            ^
SyntaxError: invalid syntax

Улучшение модуля asyncio

Модуль asyncio для поддержки асинхронности был представлен в Python 3.4 (введение). В Python 3.7 asyncio получил большое количество новых функций, поддержку контекстных переменных и улучшения производительности. Например, используя asyncio.run(), вы можете легко вызывать корутины из синхронного кода, не создавая event loop.

import asyncio

async def hello_world():
    print("Hello World!")

asyncio.run(hello_world())

PEP 567, Контекстные переменные

Контекстные переменные — это переменные, которые могут иметь различные значения в зависимости от окружения. Они похожи на Thread-Local Storage, в которых каждый исполняемый тред может иметь разное значение переменной, однако контекстные переменные могут иметь разные значение даже в пределах одного треда. Основная область применения — параллельные асинхронные задачи.

import contextvars

name = contextvars.ContextVar("name")
contexts = list()

def greet():
    print(f"Hello {name.get()}")

# Construct contexts and set the context variable name
for first_name in ["Steve", "Dina", "Harry"]:
    ctx = contextvars.copy_context()
    ctx.run(name.set, first_name)
    contexts.append(ctx)

# Run greet function inside each context
for ctx in reversed(contexts):
    ctx.run(greet)

Запуск скрипта приветствует Steve, Dina, и Harry в обратном порядке:

$ python3.7 context_demo.py
Hello Harry
Hello Dina
Hello Steve

Импорт файлов с данными с помощью importlib.resources

Как происходила упаковка ресурсов в пакет до Python 3.7? Обычно выбирали один из трёх способов

  • Захардкоженные пути к ресурсам
  • Поместить файлы внурь пакета и получать к ним доступ с помощью __file__
  • Использовать setuptools.pkg_resources

Первый способ не портируем. Второй подходит лучше, но если Python-пакет находится внутрь zip архива, то там не будет атрибута __file__, что создает проблемы. Третий способ работает, однако слишком медленный.

Теперь появляется ещё один способ: новый модуль importlib.resources в стандартной библиотеке. Он использует уже существующую функциональность импорта модулей для загрузки файлов. Допустим, у вас есть ресурсы внутри пакета:

data/
│
├── alice_in_wonderland.txt
└── __init__.py

Теперь вы можете получить доступ к alice_in_wonderland.txt следующим образом:

>>> from importlib import resources
>>> with resources.open_text("data", "alice_in_wonderland.txt") as fid:
...     alice = fid.readlines()
... 
>>> print("".join(alice[:7]))
CHAPTER I. Down the Rabbit-Hole

Alice was beginning to get very tired of sitting by her sister on the
bank, and of having nothing to do: once or twice she had peeped into the
book her sister was reading, but it had no pictures or conversations in
it, ‘and what is the use of a book,’ thought Alice ‘without pictures or
conversations?’

Похожая функция resources.open_binary() открывает файлы в бинарном режиме.

Оптимизации

Ни один релиз Python не обходится без набора оптимизаций. Python 3.7 не стал исключением:

  • Снижены накладные расходы при вызове многих методов из стандартной библиотеки
  • В целом методы теперь вызываются на 20% быстрее
  • Время запуска самого Python снижено на 10-30%
  • Импортирование typing теперь быстрее в 7 раз.

Различные лучшения CPython

  • Уход от ASCII как от дефолтной кодировки:
  • PEP 552, Воспроизводимые .pycs
  • Новая опция -X
    $ python3.7 -X importtime my_script.py
    import time: self [us] | cumulative | imported package
    import time:      2607 |       2607 | _frozen_importlib_external
    ...
    import time:       844 |      28866 |   importlib.resources
    import time:       404 |      30434 | plugins
    
    Вы также можете использовать -X dev для активации «режима разработки» и -X utf8 для активации режима UTF-8. Полный список опций.
  • PEP 565, улучшенная обработка DeprecationWarning

>>> Новость на Real Python

>>> Официальный обзор изменений

Ответ на: комментарий от no-such-file

1500 страниц

зациклились на размере этого учебника

Потому что это объективный показатель сложности языка

Ты отождествляешь сложность и размер, а это ведь разные вещи.

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

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

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

Crocodoom ()
Ответ на: комментарий от Crocodoom

Генераторы и декораторы примитивные и очень полезные вещи (хотя может они могли бы быть реализованы чуть удобней и интуитивней, но это уже придирки), а вот метаклассы это какая-то левизна, больше похожая на побочный эффект устройства самого языка, нежели «фичу».

anonymous ()
Ответ на: комментарий от no-such-file

питон простой потому что он сложный

звучит логично ващет. Си вот сложный потому что простой. И асм тоже. Получается плюсы сложные просто потому что это си.

anonymous ()
Ответ на: комментарий от anonymous

ты прочитай всё полностью по ссылке.

Я прочитал. «Обскурный» (ц) (тм) баг, мешающий примерно никому и без очевидного способа исправления.

Питонные модули сломаны, их нельзя использовать для того, для чего они заявлены
так всё же правильно

Ты делаешь слишком далеко идущие выводы из своего опыта (кстати, к метаклассам это тоже относится).

tailgunner ★★★★★ ()
Ответ на: комментарий от Crocodoom

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

Это же можно сказать о любом скриптовом языке. Учится за неделю. Но в отличие от питона целиком и никаких «остальных концепций» выяснять потом не нужно.

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

Именно так.

Вот только в индустрии и такие «незнайки» вполне востребованы, а тогда так ли оно важно, это знание всех нюансов?

Не сомневаюсь. Но я уже устал тут повторять всем и каждому, что:

1.Мнение таких незнаек о простоте питона ложно, они просто не знают питон и не сталкивались со сложностями, потомучто пишут только хеловорды по методичкам прочитав «первую главу».

2.Если по большому счёту это всё что требуется «индустрии», то питон является необоснованно переусложнённым языком и его «фичи» просто не нужны.

поэтому я называю его несложным, но большим

Величина сама по себе тоже является сложностью, т.к. требует больше времени на изучение, больше усилий для запоминания большого количества деталей и т.д. Более того, те аспекты языка которые редко востребованы постепенно забываются, что потом требует новых усилий для повторного изучения. Кстати, я вовсе не считаю что незнайки питона тупые, просто язык настолько большой что нормальному человеку трудно его освоить во всей полноте. Поэтому большинство и ограничивается первой главой - это с одной стороны достаточно просто для изучения, а с другой достаточно для того чтобы писать программы. В общем см.п.2 выше.

no-such-file ★★★★★ ()
Последнее исправление: no-such-file (всего исправлений: 2)
Ответ на: комментарий от no-such-file

просто не знают питон и не сталкивались со сложностями ... его «фичи» просто не нужны.

Отут ошибка. Если фичи не нужны «незнайкам» это не означает, что они не нужны тем, кто обеспечивает им возможность не знать. Вполне вероятно, что без чёрной магии в кишках системы будет невозможно создать видимость простоты снаружи. И что же в этом необычного - «везде» есть «пользователи», которым нужно предоставить простой очевидный интерфейс, и «ижненеры», которые знают, из каких костылей это состоит. И это есть хорошо.

DonkeyHot ★★★★★ ()
Ответ на: комментарий от DonkeyHot

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

В других языках не требуется никакой чёрной магии для этого. Отсюда следует, что питон просто broken by design, если он не может обойтись без чёрной магии, там где другие могут, и весь python way это дорога в ад.

Зря ты пытаешься оправдать сложность питона магическими свойствами присущими только питону.

no-such-file ★★★★★ ()
Ответ на: комментарий от no-such-file

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

Это же можно сказать о любом скриптовом языке. Учится за неделю. Но в отличие от питона целиком и никаких «остальных концепций» выяснять потом не нужно.

4.2

anonymous ()
Ответ на: комментарий от no-such-file

В других языках не требуется никакой чёрной магии для этого. Отсюда следует, что питон просто broken by design, если он не может обойтись без чёрной магии, там где другие могут, и весь python way это дорога в ад.

Напиши, хоть, в каких языках и какая конкретно черная магия

anonymous ()
Ответ на: комментарий от no-such-file

В других языках не требуется никакой чёрной магии

JS - не магия, но бесконечное количество «ритуалов», а то типы заглючат, области видимости пересекутся. Я не говорю о том, что зазеваешься - и вот уже у тебя множатся копии объектов и едят память, вместо подразумевавшегося вызова функции в цикле.

Вообще, питон - годная замена турбо-паскалю. Естественно, когда за типами следишь (или следит IDE)

Shadow ★★★★★ ()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от anonymous

какая конкретно черная магия

Мне сюда все 1500 пресловутых страниц скопипастить? Сходи и почитай.

в каких языках

Тут другой анонимус уже приводил пример с абстрактным классом на метаклассах. Почему-то в пыхе никаких метаклассов и другой магии для этого не нужно.

no-such-file ★★★★★ ()
Ответ на: комментарий от anonymous

Да взять хоть ООП: если требуется что-то чуть сложнее словаря с методами, начинаются дикие пляски с бубном. Нигде не видел более неуклюжей примитивной и одновременно сложной в применении объектной модели.

bread ()
Ответ на: комментарий от no-such-file

Тут другой анонимус уже приводил пример с абстрактным классом на метаклассах. Почему-то в пыхе никаких метаклассов и другой магии для этого не нужно.

То что не нужно без причины использовать мета и абстрактные классы писали уже неоднократно. Это просто надо принять «как есть». Константы, приватные и защищенные методы помечаются используя правила именования (верхний регистр, двойной и одинарный символ подчеркивания). И все, рисуйте дерево класса любой сложности - ненужно никакой магии. Кстати, сомневаюсь, что для любителя php это аргумент, но даже с метаклассами и дескрипторами «магии» все-равно меньше чем в Ruby. Пример продуманного пыха:

("x" == 0) === true
("1x" == 0) === false
У Гвидо хоть какой-то здравый смысл был, когда он к типам операторы приделывал.

anonymous ()
Ответ на: комментарий от no-such-file

Манипуляция строками, списками, работа с csv, json - все есть «из коробки»

Это практически везде есть из коробки. В том же пыхе например.

Может сравним КАК это делается в Python и PHP?

anonymous ()

Мда, приводить как доказательство сложности языка книжку Лутца... Там отдельные главы страниц по 30 для описания оператора if и циклов. И книжка для совсем начинающих, которые вообще никакого ЯП не знают, ни программировать не умеют. Как второй язык после С/Pascal/Java Python учится элементарно, и легко воспринимается как интуитивно понятный псевдокод. Сложность ЯП логичнее сравнивать по объему описания грамматики и официальной документации. Посмотрите официальный Language Reference (там описания операторов if, for по 1 абзацу). Хотите короткий учебник - читайте Head first python (~400 страниц).

MyLord ()
Ответ на: комментарий от no-such-file

Чем больше требуется объяснений, тем сложнее предмет, это же очевидно.

Михаил Сергеевич Горбачём мог 3 часа болтать абсолютно ни о чём. Это не показатель сложности «ни о чём». Это показатель способностей генсека.

ugoday ★★★★★ ()
Ответ на: комментарий от Shadow

питон - годная замена турбо-паскалю

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

grem ★★★★★ ()
Ответ на: комментарий от no-such-file

других языках не требуется никакой чёрной магии

А есть ли в них же(тех, которые без магии) иллюзия простоты? Нужно бы покорелировать «количество магии» и «среднее мнение о простоте».

Я надумал согласиться с чьим-то мненем выше об объективной природе сложности. Постулируем «Закон неубывания». Никакой магический инструмент не может уменьшить сложность. Её можно только перераспределить - между «прикладным» и «библиотечным» кодом. И это неминуемо добавит дополнительную сложность. Которую можно попытаться спрятать в язык, или вывалить на «прикладника» и/или «библиотекаря». Больше просто некуда(можно в другой язык, но это юниксвей и офтопик).

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

DonkeyHot ★★★★★ ()
Последнее исправление: DonkeyHot (всего исправлений: 1)
Ответ на: комментарий от anonymous

не нужно без причины использовать мета и абстрактные классы писали уже неоднократно

Я даже больше скажу, их вообще не нужно использовать. Никогда. В питоне они на практике никому не нужны.

Пример продуманного пыха

А я где-то утверждал что пых продуманный? Пых язык практичный, а это означает что в нём есть костыли, т.к. на практике просто невозможно создать идеально продуманный «язык всего», будь ты хоть Гвидо, хоть сам Христос. Создатели пыха хотя бы не строят из себя святых. И кстати говоря про == обсуждается возможность его выкинуть, оставить только ===.

no-such-file ★★★★★ ()
Ответ на: комментарий от DonkeyHot

В батарейки она не пролезет - никто не станет писать их добровольно, и никто не станет покупать их достаточно дорого, чтобы окупить труд рабов

Что называется «начал за здравие, кончил за упокой». Ты опять апеллируешь в «волшебному свойству». Только раньше это было свойство языка, а теперь это свойство сообщества.

никто не станет писать их добровольно

Конечно станет, и пишут. И для питона пишут, и для других языков.

no-such-file ★★★★★ ()
Ответ на: комментарий от anonymous

Высшее образование нужно для нормальных инженеров.

Бывает так, что зачастую нормального инженера (имеющего высшее образование) не отличишь от алкаша-слесаря окончившего профессиональный техникум.

Также, бывает так, что встречаешь вежливого интеллигентного очкарика со среднеспециальным образованием.

Вот и думаешь: «а на куя оно, это высшее образование».

anonymous ()
Ответ на: комментарий от no-such-file

волшебному свойству ... сообщества

Лень и нежелание «трудиться»(в противовес «развлекаться») - это вовсе не магические свойства человеков. Они были бы магическими, если бы отсутствовали.

DonkeyHot ★★★★★ ()
Ответ на: комментарий от anonymous

бывает так, что встречаешь вежливого интеллигентного очкарика со среднеспециальным образованием.

Вот и думаешь: «а на куя оно, это высшее образование».

Высшее образование - оно точно не для очков и вежливости :)

tailgunner ★★★★★ ()
Ответ на: комментарий от no-such-file

Пых язык практичный, а это означает все что в нём есть - костыли

fixed :) Когда из языка для создания home page начали делать пародию на джаву, иначе и быть не может.

Linfan ★★★★★ ()
Ответ на: Аннотации типов от Laz

можно, будет что-то типа Callable[Callable[a, [f, b], Callable...

кстати, над typing и mypy сам гвидо достаточно активно работает на гитхабе и он вместе с другими разработчиками отвечает на вопросы юзеров по аннотации каких-то сложных ситуаций (сам ничего там не спрашивал, но находил там поиском решения для сложных ситуаций)

actionless ★★★★★ ()