!python --version
Python 3.8.0rc1
Страница запуска
Python 3.8 – главный выпуск Python. Вот раунд некоторых новых функций.
- Новые правила синтаксиса!
- Параллельные данные OPS Улучшения!
- Функции проверки статического типа!
- CPYPHON Вещи!
Давайте начнем с нового правила синтаксиса:
Назначение в выражениях (PEP 572)
Теперь Python позволяет создавать переменные внутри выражений (например, тело понимания списка.)
def f(x): for k in range(10000000): x*x*x/x+x+x+x+x return x x = 2 # Reuse a value that's expensive to compute %timeit [y := f(x), y**2, y**3] # Without reuse %timeit [f(x), f(x)**2, f(x)**3]
1.78 s ± 13.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 5.45 s ± 93.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Делать это в «голым» выражении сильно обескуражено в PEP. Смотрите: Исключительные случаи
PEP 572.
Вот еще одно новое правило синтаксиса:
Только позиционные args (PEP 570)
Этот смутил меня, пока я не прокручиваюсь до сечения синтаксиса, поэтому давайте просто увидимся в действии:
def prelaunch_func(foo, bar, baz=None): print(f"\nFoo:{foo}\nBar:{bar}\nBaz:{baz}") def pep570_func(foo, /, bar, baz=None): print(f"\nFoo:{foo}\nBar:{bar}\nBaz:{baz}")
/
В подписи вызова pep570_func
Обозначает, где args только позиционные args. Эти функции позволят нам увидеть практическую разницу PEP 570 приводов.
prelaunch_func(foo=1, bar=2, baz=3)
Foo:1 Bar:2 Baz:3
# Violating positional-only pep570_func(foo=1, bar=2, baz=3)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last)in 1 # Violating positional-only ----> 2 pep570_func(foo=1, bar=2, baz=3) TypeError: pep570_func() got some positional-only arguments passed as keyword arguments: 'foo'
# This is fine, as bar is right of the "/" in the call signature pep570_func(1, bar=2, baz=3)
Foo:1 Bar:2 Baz:3
# This was wrong before PEP-570 of course pep570_func(foo=1, 2, baz=3)
File "", line 2 pep570_func(foo=1, 2, baz=3) ^ SyntaxError: positional argument follows keyword argument
То, что мне нравится больше всего в этом, если вы также можете иметь позиционные аргументы только с значениями по умолчанию, как показано здесь:
def pep570_func(foo, bar=None, baz=1, /): print(f"\nFoo:{foo}\nBar:{bar}\nBaz:{baz}") pep570_func(10)
Foo:10 Bar:None Baz:1
# But don't mistake them for kwargs pep570_func(10, bar=1)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last)in 1 # But don't mistake them for kwargs ----> 2 pep570_func(10, bar=1) TypeError: pep570_func() got some positional-only arguments passed as keyword arguments: 'bar'
Для получения более подробной информации о проверке PEP: Pep-570.
Теперь давайте перейдем к некоторой параллельной обработке данных:
Общая память и новые соленья
Два важных улучшения в 3.8 были вдохновлены библиотеками, такими как DASC которые пытаются решить проблему передачи данных между процессами. Один – создать новую версию Парил
Это может передавать объекты данных между процессами с использованием буферов с нулевым копированием, для более эффективного совместного использования памяти.
Общая тема этих сторонних усилий сериализации состоит в том, чтобы генерировать поток метаданных объекта (который содержит сообразующую информацию об объектах, являющихся сериализуемыми) и отдельный поток объектов буферов нулевого копирования для полезных нагрузок крупных объектов. Обратите внимание, что в этой схеме небольшие объекты, такие как ints и т. Д., Могут быть сбрасываться вместе с потоком метаданных. Уточнения могут включать оппортунистическое сжатие больших данных в зависимости от его типа и макета, как dass.
Этот PEP направлен на то, чтобы сделать совокупность таким образом, когда большие данные обрабатываются как отдельный поток буферов нулевой копии, позволяя приложению обрабатывать эти буферы оптимально.
Pep-574.
Другой Biggie в этой категории заключается в том, что процессы имеют новый интерфейс для совместной памяти: SharedMemory
и SharedMemoryManager
Отказ Документы имеют очень захватывающий пример:
import multiprocessing from multiprocessing.managers import SharedMemoryManager # Arbitrary operations on a shared list def do_work(shared_list, start, stop): for idx in range(start, stop): shared_list[idx] = 1 # Example from the docs with SharedMemoryManager() as smm: sl = smm.ShareableList(range(2000)) # Divide the work among two processes, storing partial results in sl p1 = multiprocessing.Process(target=do_work, args=(sl, 0, 1000)) p2 = multiprocessing.Process(target=do_work, args=(sl, 1000, 2000)) p1.start() p2.start() # A multiprocessing.Pool might be more efficient p1.join() p2.join() # Wait for all work to complete in both processes total_result = sum(sl) # Consolidate the partial results now in sl # `do_work` set all values to 1 in parallel print(f"Total of values in shared list: {total_result}")
Total of values in shared list: 2000
Осталось увидеть, если эти улучшения создают счастливый путь, который примет сосредоточенные библиотеки параллельных опс. В любом случае это интересно. Проверьте SharedMemory
здесь .
Теперь давайте посмотрим на некоторые статические типы, проверяющие вещи:
Напечатанные словари (PEP 589)
Введите подсказки Не накрывают вложенные диктовые диктографии, а Dataclasses не разобрасывают Джосон достаточно хорошо, поэтому теперь Python будет поддерживать некоторые статические проверки типа на словарях с известным набором ключей. Рассмотрим сценарий ниже:
# scripts/valid_589.py from typing import TypedDict class Movie(TypedDict): name: str year: int # Cannonical assignment of Movie movie: Movie = {'name': 'Wally 2: Rise of the Garbage Bots', 'year': 2055}
Marpy
пройдет это без вопросов, потому что словарь является действительной реализацией типа.
!mypy scripts/valid_589.py
[1m[32mSuccess: no issues found in 1 source file[m
Теперь рассмотрим недопустимый скрипт ниже – он имеет значения неправильных типов:
# scripts/invalid_values_589.py from typing import TypedDict class Movie(TypedDict): name: str year: int def f(m: Movie): return m['year'] f({'year': 'wrong type', 'name': 12})
!mypy scripts/invalid_values_589.py
scripts/invalid_values_589.py:10: [1m[31merror:[m Incompatible types (expression has type [m[1m"str"[m, TypedDict item [m[1m"year"[m has type [m[1m"int"[m)[m scripts/invalid_values_589.py:10: [1m[31merror:[m Incompatible types (expression has type [m[1m"int"[m, TypedDict item [m[1m"name"[m has type [m[1m"str"[m)[m [1m[31mFound 2 errors in 1 file (checked 1 source file)[m
Вы также можете проверить отсутствующие значения, неверные поля или создайте Типичный
S, что примет недостающие значения, используя Всего = Ложь
с конструктором.
PEP 589.
Окончальность (PEP 591)
3.8 также реализует окончание. Мы можем предотвратить переопределение объектов или унаследовано. @final
Декоратор можно использовать с класс
Определение, чтобы предотвратить наследование, а Финал
Тип предотвращает переопределение. Вот два примера от PEP:
# Example 1, inheriting a @final class from typing import final @final class Base: ... class Derived(Base): # Error: Cannot inherit from final class "Base" ... # Example 2, overriding an attribute from typing import Final class Window: BORDER_WIDTH: Final = 2.5 ... class ListView(Window): BORDER_WIDTH = 3 # Error: can't override a final attribute
Окончальность может быть применена к методам, атрибутам и наследству. Проверьте все функции в PEP 591.
Литералы (PEP 586)
Подпись подсказки к типу def f (k: int):
не помогает нам, если функция ожидает int
s в диапазоне. открыть
требует Режим: ул
аргумент из определенного набора строк. Буквальный
С для спасения!
# scripts/problematic_586.py def problematic_586(k: int): if k < 100: return k else: raise ValueError('Gotta be less than 100') problematic_586(144)
!mypy scripts/problematic_586.py
[1m[32mSuccess: no issues found in 1 source file[m
Вместо этого мы можем пройти Буквальный
к типу намекании на наш аргумент k
.
# scripts/valid_586.py from typing import Literal def valid_586(k: Literal[0, 1, 2, 99]): if k < 100: return k else: return float(k) valid_586(43)
!mypy scripts/valid_586.py
scripts/valid_586.py:8: [1m[31merror:[m Argument 1 to [m[1m"valid_586"[m has incompatible type [m[1m"Literal[43]"[m; expected [m[1m"Union[Literal[0], Literal[1], Literal[2], Literal[99]]"[m[m [1m[31mFound 1 error in 1 file (checked 1 source file)[m
Есть немного нюанса для использования Буквальный
Так что, если вы решите исследовать дальше начать с Pep-586 Отказ
И это все! Я собираюсь удержать на писать о функциях CPY-CPY, потому что, честно говоря, я бы предпочел не писать о них, пока я не буду писать оружия более жестко вокруг Cpython, как правило, и эти особенности в частности.
Спасибо за чтение!
Слияние Если вы хотите поиграть с любым из примеров в этом блоге или испытательном приводе Python3.8, не устанавливая его, я предоставляю исходный репозиторий для этого блога ниже. Он включает в себя DockerFile, который вращает на a Python 3.8 Jupyterlab окружающую среду.
Charlesdlandau/python38_blog.
Репо с исходным материалом для блога
Это исходный репо для этого блога, а также включает в себя DockerFile для простого запуска Python 3.8 без необходимости установки его локально. Так:
//build docker build -t. //run on *nix docker run -p 8888:8888 -it --rm -v $(PWD):/code --name dev //run on windows docker run -p 8888:8888 -it --rm -v %CD%:/code --name dev
Если все идет хорошо, вам будет предложено скопировать URL в ваш браузер, который будет указывать на ваш локальный порт 8888 с токеном для авторизации доступа к экземпляру Jupyter.
Оригинал: “https://dev.to/charlesdlandau/python-3-8-has-been-released-let-s-take-a-tour-bj3”