Uma declaração "with" suporta dicas de tipo?

16

Você pode definir a dica de tipo para uma variável definida com a withsintaxe?

with example() as x:
    print(x)

Gostaria de digitar dica acima para dizer que xé um str(como exemplo).

A única solução alternativa que eu encontrei é usar uma variável intermediária, mas isso parece hacky.

with example() as x:
    y: str = x
    print(y)

Não consigo encontrar um exemplo na documentação de digitação .

Reactgular
fonte
6
Os verificadores de tipo não devem poder deduzir o tipo de xcomo o tipo de retorno example().__enter__()?
pschill 11/02
2
Por que você deseja anotar xquando é simplesmente o tipo de retorno example.__enter__? Idealmente, você anotou esse método / função.
a_guest 11/02
11
xnão é o valor de retorno de example; é o valor de retorno de example().__enter__().
chepner 11/02
A maioria dos métodos que encontrei não define uma dica de tipo para o valor de retorno.
Reactgular
11
@ Reactgular Em seguida, a solução é criar um arquivo stub para essa função, para que o verificador de tipos possa inferir o tipo. Geralmente você faz anotações nos limites da API, não dentro. Nesse caso, é claro que o tipo vem example. Anotar example.__enter__significa uma anotação enquanto você usa sua abordagem em todos os lugares em que esse gerenciador de contexto é usado, além de, em geral, como um usuário deve saber qual é o tipo de retorno de uma API se ela não for fornecida?
a_guest 11/02

Respostas:

11

O PEP 526, que foi implementado no Python 3.6, permite anotar variáveis. Você pode usar, por exemplo,

x: str
with example() as x:
    [...]

ou

with example() as x:
    x: str
    [...]
pschill
fonte
Isso também funciona para outros blocos de código como for. Ótima resposta, obrigado.
Reactgular
Se o gerenciador de contexto não sugerir o que o __enter__método retornará, a digitação xnão serve para nada. mypyfelizmente permitirá que um valor de qualquer tipo seja vinculado x.
chepner 11/02
@chepner Sim, você está certo. O PyCharm reconhece xcomo strnos dois casos, mas mypynão.
pschill 11/02
14

Geralmente, as anotações de tipo são colocadas nos limites da API. Nesse caso, o tipo deve ser deduzido de example.__enter__. Caso essa função não declare nenhum tipo, a solução é criar um arquivo stub correspondente para ajudar o verificador de tipos a inferir esse tipo.

Especificamente, isso significa criar um .pyiarquivo com a mesma raiz do módulo a partir do qual Examplefoi importado. Em seguida, o seguinte código pode ser adicionado:

class Example:
    def __enter__(self) -> str: ...
    def __exit__(self, exc_type, exc_value, exc_traceback) -> None: ...
um convidado
fonte