¿Una declaración "con" admite sugerencias de tipo?

16

¿Puedes definir la sugerencia de tipo para una variable definida con la withsintaxis?

with example() as x:
    print(x)

Me gustaría escribir una pista de lo anterior para decir que xes un str(como ejemplo).

La única solución que he encontrado es usar una variable intermedia, pero esto se siente extraño.

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

No puedo encontrar un ejemplo en la documentación de escritura .

Reactgular
fuente
66
¿No deberían los correctores de tipo poder deducir el tipo de xcomo el tipo de retorno de example().__enter__()?
pschill
2
¿Por qué quieres anotar xcuando es simplemente el tipo de retorno de example.__enter__? Idealmente, ha anotado ese método / función.
a_guest
1
xno es el valor de retorno de example; Es el valor de retorno de example().__enter__().
chepner
La mayoría de los métodos que he encontrado no definen una pista de tipo para el valor de retorno.
Reactgular
1
@Reactgular Entonces la solución es crear un archivo apéndice para esa función, de modo que el verificador de tipos pueda inferir el tipo. Por lo general, anota en los límites de la API, no dentro. En este caso, está claro de qué tipo proviene example. Anotar example.__enter__significa una anotación, mientras que con su enfoque tendría que anotar en todos los lugares donde se usa ese administrador de contexto, además, en general, ¿cómo se supone que un usuario sabe cuál es el tipo de retorno de una API de todos modos si no se proporciona?
a_guest

Respuestas:

11

PEP 526, que se ha implementado en Python 3.6, le permite anotar variables. Puedes usar, por ejemplo,

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

o

with example() as x:
    x: str
    [...]
pschill
fuente
Esto también funciona para otros bloques de código como for. Gran respuesta, gracias.
Reactgular
Si el administrador de contexto no sugiere qué __enter__devolverá el método, escribir xno sirve para nada. mypyfelizmente permitirá vincular un valor de cualquier tipo x.
Chepner
@chepner Sí, tienes razón. PyCharm reconoce xcomo stren ambos casos, pero mypyno lo hace.
pschill
14

Por lo general, las anotaciones de tipo se colocan en los límites de API. En este caso, el tipo debe inferirse de example.__enter__. En caso de que la función no declare ningún tipo, la solución es crear un archivo apéndice correspondiente para ayudar al verificador de tipos a inferir ese tipo.

Específicamente, esto significa crear un .pyiarchivo con la misma raíz que el módulo desde el que Examplese importó. Luego se puede agregar el siguiente código:

class Example:
    def __enter__(self) -> str: ...
    def __exit__(self, exc_type, exc_value, exc_traceback) -> None: ...
un invitado
fuente