O que há de novo esperado em Python 3.9

A nova versão é esperada apenas em outubro, mas você já pode ler o que nos espera e testar o lançamento preliminar.
Neste artigo, o mais interessante, na minha opinião, muda.

Primeiro, lembramos que as camadas que suportam compatibilidade com versões anteriores à versão 2.7 estão sendo removidas lentamente e solicitadas a prestar atenção ao DeprecationWarning e eliminá-las. Alguns avisos ainda permanecerão em 3,9, mas é melhor se livrar deles.

Operador de
mesclagem de dicionário ( PEP-584 ) Até agora, havia várias maneiras de mesclar dicionários, mas cada um deles apresentava falhas ou nuances menores.
Várias maneiras de combinar dicionários
1. update
d1 = {'one': 1}
d2 = {'two': 2}
#     ,..
d1.update(d2)
# ...  . 
united_dict = d1.copy()
united_dict.update(d2)

2.
united_dict = {**d1, **d2}

, , , .
3. dict(d1, **d2), . , d2 .
4. collections.ChainMap
.
, , .
from collections import ChainMap
d1 = {'one': 1}
d2 = {'two': 2}
united_dict = ChainMap(d1, d2)

, , , . , - .

Agora você pode escrever simplesmente
united_dict = d1 | d2
# ,        ,    update():
d1 |= d2

Assim, acho que uma nova possibilidade de combinar dicionários com um operador atrairá muitos.

Simplificação de anotações para contêineres e outros tipos que podem ser parametrizados ( PEP-0585 )
A inovação a seguir é muito útil para quem usa anotação de tipo.
Agora simplifica a anotação de coleções, como list e dict, e tipos geralmente parametrizados.

Para esses tipos, o termo Genérico é introduzido - este é um tipo que pode ser parametrizado, geralmente um contêiner. Por exemplo, dite. E a questão é como traduzi-lo corretamente para que não quebre os dentes. Eu realmente não quero usar a palavra "genérico". Então, nos comentários, estou realmente ansioso por outras sugestões. Talvez em algum lugar nas traduções houvesse um nome melhor?
Genérico parametrizado: dict [str, int].

Portanto, para esses tipos, agora você não precisa importar as anotações correspondentes da digitação, mas pode apenas usar os nomes dos tipos.
por exemplo
# 
from typing import List
List[str]
# 
list[int]

.

:
# 
from typing import OrderedDict
OrderedDict[str, int]
# 
from collections import OrderedDict
OrderedDict[str, int]

tuple # typing.Tuple
list # typing.List
dict # typing.Dict
set # typing.Set
frozenset # typing.FrozenSet
type # typing.Type
collections.deque
collections.defaultdict
collections.OrderedDict
collections.Counter
collections.ChainMap
collections.abc.Awaitable
collections.abc.Coroutine
collections.abc.AsyncIterable
collections.abc.AsyncIterator
collections.abc.AsyncGenerator
collections.abc.Iterable
collections.abc.Iterator
collections.abc.Generator
collections.abc.Reversible
collections.abc.Container
collections.abc.Collection
collections.abc.Callable
collections.abc.Set # typing.AbstractSet
collections.abc.MutableSet
collections.abc.Mapping
collections.abc.MutableMapping
collections.abc.Sequence
collections.abc.MutableSequence
collections.abc.ByteString
collections.abc.MappingView
collections.abc.KeysView
collections.abc.ItemsView
collections.abc.ValuesView
contextlib.AbstractContextManager # typing.ContextManager
contextlib.AbstractAsyncContextManager # typing.AsyncContextManager
re.Pattern # typing.Pattern, typing.re.Pattern
re.Match # typing.Match, typing.re.Match


Para strings, os métodos removeprefix () e removeesuffix () ( PEP 616 ) apareceram.Tudo
aqui é simples. Se a linha começar com um prefixo, a linha sem esse prefixo será retornada. Se o prefixo for repetido várias vezes, ele será excluído apenas uma vez. Da mesma forma com o sufixo:
some_str = 'prefix of some string and here suffix'
some_str.removeprefix('prefix')
>> ' of some string and here suffix'
some_str.removesuffix('suffix')
>> 'prefix of some string and here '

Alternativas atuais
1. , , — removeprefix.
def removeprefix(self: str, prefix: str, /) -> str:
    if self.startswith(prefix):
        return self[len(prefix):]
    else:
        return self[:]

2. lstrip, rstrip:
	'foobar'.lstrip(('foo',))

, , .

Algumas alterações no módulo matemático
A função math.gcd () para encontrar o maior divisor comum agora aceita uma lista de números inteiros, para que você possa encontrar um divisor comum com mais de dois números.
Existe uma função para determinar o menor múltiplo comum de math.lcm () , que também aceita um número ilimitado de números inteiros.
As duas funções a seguir estão interconectadas.
math.nextafter (x, y) - calcula o número de ponto flutuante mais próximo de x se estiver se movendo na direção y.
math.ulp (x)- significa "Unidade em último lugar" e depende da precisão dos cálculos do seu computador. Para números positivos, o valor mais baixo do número será retornado, de modo que, quando for adicionado x + ulp (x), o número de ponto flutuante mais próximo seja obtido.
import math

math.gcd(24, 36)
>> 12
math.lcm(12, 18)
>> 36
math.nextafter(3, -1)
>> 2.9999999999999996
3 - math.ulp(3)
>> 2.9999999999999996
math.nextafter(3, -1) + math.ulp(3)
>> 3.0 

Agora, qualquer expressão válida pode ser um decorador ( PEP-0614 ).
A restrição é removida dos decoradores, segundo a qual apenas um nome pode atuar como decorador e sua sintaxe permite apenas a separação por pontos.

Eu não acho que muitas pessoas pensaram na existência de tal restrição, mas a descrição do pep dá um exemplo quando uma inovação torna o código mais fino. Por analogia, podemos citar
exemplo simplificado e artificial:
def a(func):
	def wrapper():
		print('a')
		func()
	return wrapper
	
def b(func):
	def wrapper():
		print('b')
		func()
	return wrapper
	
decorators = [a, b]

@decorators[0] #   3.8        
def some_func():
	print('original')
	
some_func()
>> a
>> original

O método unparse ( bpo-38870 ) foi adicionado ao módulo
ast.Como o nome indica, ele pode compilar a cadeia de origem usando o objeto ast.AST. Uma vez, eu até queria usar isso e foi surpreendente que não existisse esse método.
Exemplo:
import ast
parsed = ast.parse('import pprint; pprint.pprint({"one":1, "two":2})')
unparsed_str = ast.unparse(parsed)
print(unparsed_str)
>> import pprint
>> pprint.pprint({'one': 1, 'two': 2})
exec(unparsed_str)
>> {'one': 1, 'two': 2}

A nova classe functools.TopologicalSorter para classificação topológica de gráficos acíclicos direcionados ( bpo-17005 ) O
gráfico que é passado para o classificador deve ser um dicionário no qual as chaves sejam os vértices do gráfico e o valor é um objeto iterável com predecessores (vértices cujos arcos apontam para a chave). Como chave, como de costume, qualquer tipo de hash é adequado.
Exemplo:
:

from functools import TopologicalSorter
graph = graph = {8: [3, 7], 11: [5, 7], 2: [11], 9: [8, 11], 10: [3, 11]}
t_sorter = TopologicalSorter(graph)
t_sorted_list = list(t_sorted_list.static_order()) #  ,    ,     static_order.
>> [3, 7, 5, 8, 11, 2, 9, 10]


, TopologicalSorter add. , , .

Novos status que estamos aguardando há tanto tempo foram
adicionados ao http.HTTPStatus : 103 EARLY_HINTS
418 IM_A_TEAPOT
425 TOO_EARLY

E mais algumas alterações:
  • Tipos internos (intervalo, tupla, conjunto, frozenset, lista) são acelerados ( PEP-590 )
  • "" .replace ("", s, n) agora retorna s, não uma string vazia, para todos os n diferentes de zero. Isso vale para bytes e bytearray.
  • O ipaddress agora suporta a análise de endereços IPv6 com destinos.

Como a versão 3.9 ainda está em desenvolvimento, e talvez mais alterações sejam adicionadas, pretendo complementar este artigo conforme necessário.

Você pode ler em mais detalhes:
docs.python.org/3.9/whatsnew/3.9.html
www.python.org/downloads/release/python-390a6
Em geral, não quer dizer que futuras mudanças são o que todo mundo já estava esperando por um longo tempo e sem o qual é impossível sobreviver, embora haja alguns pontos interessantes. E o que você achou mais interessante na nova versão?

UPD:
link atualizado para a versão mais recente;
adicionado PEP-0585 sobre anotação de tipo

All Articles