Tipo de sugerencias Convención para variables de instancia Python

No estoy seguro de la convención de Python para las variables de instancia de sugerencias de tipo: las he estado haciendo dentro de los argumentos del constructor __init__ como se ve aquí:

 class LoggedVar(Generic[T]): def __init__(self, value: T, name: str, logger: Logger) -> None: self.name = name self.logger = logger self.value = value` 

enlace al fragmento de código anterior: https://docs.python.org/3/library/typing.html#user-defined-generic-types

Pero también veo las convenciones PEP de anotar variables de instancia como tales (fragmento de código a continuación) y luego también hacer sugerencias de tipo dentro de los argumentos __init__ :

 class BasicStarship: captain: str = 'Picard' # instance variable with default damage: int # instance variable without default stats: ClassVar[Dict[str, int]] = {} # class variable` def __init__(self, damage: int, captain: str = None): self.damage = damage if captain: self.captain = captain # Else keep the default 

Finalmente, más adelante en el artículo de PEP526, dicen que se puede hacer lo siguiente por conveniencia y convención:

 class Box(Generic[T]): def __init__(self, content): self.content: T = content 

url a dos fragmentos de código anteriores: https://www.python.org/dev/peps/pep-0526/#class-and-instance-variable-annotations

Entonces, ¿es una de estas convenciones mejor / más aceptada que las otras a las que debería tratar (mejor legibilidad, etc.)?

Recomendaría usar la primera versión, donde asigna tipos a los __init__ su método __init__ , para la mayoría de las circunstancias.

Ese método en particular tiene la menor cantidad de redundancia al mismo tiempo que permite que los verificadores de tipos verifiquen que está llamando correctamente al método __init__ en otra parte de su código.

Recomendaría usar la segunda o la tercera versión, donde anotar explícitamente sus campos (dentro o fuera de __init__ ) cuando su método __init__ se haya vuelto lo suficientemente complejo como para el punto donde se apliquen uno o más de los siguientes:

  1. Ya no es tan sencillo con lo que comienzan tus campos exactamente
  2. Ya no existe una asignación uno a uno entre sus parámetros y sus campos
  3. Tiene una lógica de inicialización compleja que oculta cómo se asignan sus campos.

Sin embargo, no me quedó claro si se prefería la segunda o la tercera versión; yo personalmente prefiero la tercera versión porque es más limpia conceptualmente y no parece mezclar la noción de atributos de instancia contra clase, pero no puedo negar la La segunda versión se ve más limpia.

Pregunté sobre eso en el canal de ‘tipeo’ de gitter, y obtuve la siguiente respuesta de Guido (quien, por casualidad, no sabía, hizo Python y actualmente está trabajando en mypy y escribiendo cosas relacionadas):

Parece que hay opiniones fuertes de cualquier manera. De hecho, prefiero poner anotaciones de atributos en el cuerpo de la clase en lugar de __init__ en __init__ y otros métodos. También creo que con PEP 526 este será el futuro (también con cosas como las declaraciones de NamedTuple basadas en clases y posiblemente https://github.com/ericvsmith/dataclasses ).

( enlace para citar )

Entonces, parece que la segunda versión se recomienda sobre la tercera, ¡y que la definición de clases de esa manera se integrará más profundamente en el lenguaje Python en algún momento en el futuro!

Edición: PEP 557, las clases de datos se aceptaron recientemente y parecen estar en camino (?) Para ser incluidas con Python 3.7.

Me apegaría a lo que estás haciendo en LoggedVar, sigue las mismas reglas que en todos los demás lugares de Python, por lo que hay menos confusión en todo.

La clase BasicStarShip cambia el scope de las variables al moverlas fuera de la función __init__. Con el capitán declarado allí, BasicStarShip.captain devolverá ‘Picard’.

Las anotaciones PEP526 son agradables de leer, pero es una nueva regla para un caso específico, la función __init__. Del zen de Python : “Los casos especiales no son lo suficientemente especiales para romper las reglas”.