En Python, ¿hay alguna manera de distinguir entre cadenas y otros iterables de cadenas?
Una str es válida como tipo Iterable[str] , pero puede que no sea la entrada correcta para una función. Por ejemplo, en este ejemplo trivial que pretende operar en secuencias de nombres de archivos:
from typing import Iterable def operate_on_files(file_paths: Iterable[str]) -> None: for path in file_paths: ...Pasar un solo nombre de archivo produciría un resultado incorrecto, pero la verificación de tipo no lo detectaría. Sé que puedo verificar tipos de bytes o cadenas en tiempo de ejecución, pero quiero saber si es posible detectar errores tontos como ese con una herramienta de verificación de tipos.
Revisé el módulo collections.abc y no parece haber ningún abc que incluya iterables típicos (por ejemplo, listas, tuplas) pero excluya cadenas. De manera similar, para el módulo de typing , no parece haber un tipo para iterables que no incluyan cadenas.
Este tema se ha discutido desde al menos julio de 2016. Sobre una propuesta para distinguir entre str e Iterable[str] , Guido van Rossum escribe:
Dado que
stres un iterable válido destr, esto es complicado. Se han hecho varias propuestas, pero no encajan fácilmente en el sistema de tipos.
Deberá enumerar todos los tipos que desea que sus funciones acepten explícitamente , utilizando Union (anterior a 3.10) o | (3.10 y superior).
por ejemplo, para versiones anteriores a 3.10, use:
from typing import Union ## Heading ## def operate_on_files(file_paths: Union[TypeOneName, TypeTwoName, etc.]) -> None: for path in file_paths: ...Para 3.10 y superior, utilice:
## Heading ## def operate_on_files(file_paths: TypeOneName | TypeTwoName | etc.) -> None: for path in file_paths: ... Si está utilizando Pytype, no tratará a str como un Iterable[str] (como lo señaló Kelly Bundy ). Sin embargo, este comportamiento es específico del verificador de tipos y no es ampliamente compatible con otros verificadores de tipos.