LINUX.ORG.RU

Python 3.7

 


5

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

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

★★★★★

Проверено: tailgunner ()
Последнее исправление: tailgunner (всего исправлений: 5)

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

Файл должен быть структурирован исходно, чтобы это работало :)

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

DRVTiny ★★★★★
()

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

AVL2 ★★★★★
()

PEP 557, Data Classes

Никак не пойму, зачем тащить этот обрезок в стандартную библиотеку, если есть attrs?

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

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

Pacmu3ka
()

Аннотации типов

А что за аннотации типов такие? Помнится, был РЕР про аннотоции, который был про синтаксис вида def lol(a: Foo, b: Bar) -> Baz, и эти Foo, Bar и Baz как-то там можно было вытягивать в рантайме. Оно доросло до типов? Статический анализ умеет? Можно написать (a -> f b) -> (t a) -> f (t b)?

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

Чтобы потешить извращенцев. Заморачивается, указывааешь типы, а оно, лол, ничего не значит. Мазохизм чистой воды, если не считать профитов для документации и сомнительных профитов от mypy.

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

Заморачивается, указывааешь типы, а оно, лол, ничего не значит

Просто ты не знаешь, зачем в Python были добавлены аннотации.

tailgunner ★★★★★
()

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

Ende
()

В УМЕРАЮЩЕМ Ruby , уже jit ускорение сделали изкаробки, когда в питоне ждать или всю жизнь ставить костыли типо pypy

anonymous
()

до прихода версии Python 4.0

Шо, опять?!

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

Синтаксис питона с современным js +- то же самое. А вот реализация js на сервере (node.js) убога донельзя. Стагнация во все поля: походу все сбежали на go.

Самый яркий пример — интеграция с бинарными либами. Много лет у ноды не было стабильного ABI. Только год назад попытались что-то добавить, но пока неочень заходит (всем пофиг, все сбежали на go)

В питоне же не только стабильный ABI с самого начала, но еще и ffi из коробки, что позволяет подключать к питону .so-шечки без единой строки на СИ

Другой пример — async/await. Синтаксис-то гугл добавила в V8, но в nodejs вся стандартная либа как была так и останется на Event-ах и callback-ах. Питонисты же запилили себе полноценную поддержку всего необходимого с async в стандартную либу

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

Go это не тот язык из которого сишечку не стоит трогать НИКАК? У питони с сишечкой любовь на век например. Как вы собрались жс с си интегрировать я хз, абсолютно разные вещи же.

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

Go это не тот язык из которого сишечку не стоит трогать НИКАК?

WUT

Как вы собрались жс с си интегрировать я хз, абсолютно разные вещи же

Я же приводил ссылку. Но разработчики не торопятся использовать. Кроме-того, n-api не отменяет необходимости писать прослойку на Си, а значит конпелять

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

Особенно, когда нужно асинхронно сходить в сеть и тут без стороннего костыля типо aiohttp не обойтись, который при установке тянет за собой еще 4 библиотеки, сам aio aiohttp естественно работает на нодовской libuv

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

WUT

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

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

anonymous
()

Релиз вообще ни о чем...

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

Наглое 4.2

Особенно, когда нужно асинхронно сходить в сеть и тут без стороннего костыля типо aiohttp не обойтись

Ты, должно быть, имел в виду не просто сеть, а HTTP и websockets

который при установке тянет за собой еще 4 библиотеки

😱

сам aio aiohttp естественно работает на нодовской libuv

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

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

Главное, что cgo позволяет подключать so-шки без написания прослойки на Си. А производительность будет все-равно выше питона и ноды

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

Генераторы, это не только про «ленивые коллекции» если что

Не от хорошей жизни.

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

Асинхронность / многопоточность это не про python.

умвр

Просто ты ннп.

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

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

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

Для использования сторонними инструментами. Сам Python игнорирует аннотации by design, так что в «ничего не значит» нет никакого «лол».

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

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

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

Ты комментарии до половины читаешь?

Я читаю их полностью, не переживай. Даже историю правок иногда читаю.

а мне капитан не требуется

Возможно, другим будет полезно иметь представление о реальном уровне твоих знаний.

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

модификаторы доступа в языке это defective by design, например. Поскольку снижают возможности для code reuse.

Бугага. Ну тогда зачем этот Пайтон нужен с кривым ООП? Пишите на Сях в процедурном стиле.

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

Перед кем ты кривляешься, клоун?

Прокукарекал радужный боевой гей, стоя перед зеркалом. Бугага!

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

Заморачивается, указывааешь типы, а оно, лол, ничего не значит

Это как в MySQL - указываешь check constraints, а он все-равно в базу данных пропихивает любые данные.

The CHECK clause is parsed but ignored by all storage engines.

Бугага!

FilosofeM ★★
()

Радуемся новой версии родного питошика! А еще вот оптимизации производительности - вах!

I-Love-Microsoft ★★★★★
()

Он уже перестал тормозить и жрать память?

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

Через твои комментарии познаётся только реальный уровень твоей борзоты.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от I-Love-Microsoft

Каковы же причины отсутствия приватных полей классов и модулей?

Двойное подчёркивание - приватное поле. Одинарное - protected. Кого у вас там отсутствие?

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

Гвидобейсик ущербный by design и не годится для сложных проектов,

Согласен. Предлагаю все успешные питонопроекты объявить несуществующими.

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

Не путай потоки с процессами

Кек, это в линуксе-то?

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

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

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

Если сравнивать с альтернативами типа php perl, то питон однозначно удобней perl и продуманней чем php

ism ★★★
()
Последнее исправление: ism (всего исправлений: 3)
Ответ на: комментарий от Ende

ущербность языка не отменяет существования успешных проектов на нем

Хорошо. А что тогда отменяет эти самые успешные проекты?

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

Сначала читать до переноса строки всем кроме 1-го.... И читать не до своего барьера, а до барьер + ищем конец строки

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

Приватные поля нарушают дзен питона: явное, лучше неявного. А так как одно из свойст питона это рефлексия, то есть возможность исследовать в рантайме, код и состояние интерпретатора, то уже из коробки есть способы посмотреть любое поле, любой структуры.

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

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

Ende
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.