para interprete how empty choose change python pycharm python-3.4 python-3.5 type-hinting

python - how - pycharm interpreter empty



Indicación tipo pitón sin importaciones cíclicas. (4)

Creo que la forma perfecta debería ser importar todas las clases y dependencias en un archivo (como __init__.py ) y luego from __init__ import * en todos los demás archivos.

En este caso tu eres

  1. evitando múltiples referencias a esos archivos y clases y
  2. También solo hay que agregar una línea en cada uno de los otros archivos y
  3. el tercero sería el conocimiento de todas las clases que podrías usar.

Estoy tratando de dividir mi gran clase en dos; Bueno, básicamente en la clase "principal" y una mezcla con funciones adicionales, como por ejemplo:

# main.py import mymixin.py class Main(object, MyMixin): def func1(self, xxx): ... # mymixin.py class MyMixin(object): def func2(self: Main, xxx): # <--- note the type hint ...

Ahora, mientras esto funciona bien, la sugerencia de tipo en MyMixin.func2, por supuesto, no puede funcionar. No puedo importar main.py, porque obtendría una importación cíclica y, sin la pista, mi editor (PyCharm) no puede decir qué es self .

Utilizando Python 3.4, dispuesto a pasar a 3.5 si hay una solución disponible allí.

¿Hay alguna forma en que pueda dividir mi clase en dos archivos y mantener todas las "conexiones" para que mi IDE todavía me ofrezca la finalización automática y todas las otras cosas que se derivan de ella al conocer los tipos?


El problema más grande es que, para empezar, tus tipos no están cuerdos. MyMixin hace una suposición codificada de que se mezclará con Main , mientras que podría mezclarse con cualquier número de otras clases, en cuyo caso probablemente se rompería. Si su mezcla está programada para ser mezclada en una clase específica, también puede escribir los métodos directamente en esa clase en lugar de separarlos.

Para hacer esto correctamente con una escritura sana, MyMixin debe codificarse contra una interfaz , o clase abstracta en el lenguaje Python:

import abc class MixinDependencyInterface(abc.ABC): @abc.abstractmethod def foo(self): pass class MyMixin: def func2(self: MixinDependencyInterface, xxx): self.foo() # ← mixin only depends on the interface class Main(MixinDependencyInterface, MyMixin): def foo(self): print(''bar'')


No hay una forma muy elegante de manejar los ciclos de importación en general, me temo. Sus opciones son rediseñar su código para eliminar la dependencia cíclica o, si no es posible, hacer algo como esto:

# some_file.py from typing import TYPE_CHECKING if TYPE_CHECKING: from main import Main class MyObject(object): def func2(self, some_param: ''Main''): ...

La constante TYPE_CHECKING siempre es False en tiempo de ejecución, por lo que la importación no se evaluará, pero mypy (y otras herramientas de verificación de tipo) evaluarán el contenido de ese bloque.

También debemos convertir la anotación de tipo Main en una cadena, declarándola de forma efectiva, ya que el símbolo Main no está disponible en tiempo de ejecución.

Si está utilizando Python 3.7+, al menos podemos omitir tener que proporcionar una anotación de cadena explícita aprovechando PEP 563 :

# some_file.py from __future__ import annotations from typing import TYPE_CHECKING if TYPE_CHECKING: from main import Main class MyObject(object): # Hooray, cleaner annotations! def func2(self, some_param: Main): ...

La from __future__ import annotations importación from __future__ import annotations hará que todas las sugerencias de tipo sean cadenas y omita evaluarlas. Esto puede ayudar a que nuestro código aquí sea ligeramente más ergonómico.

Dicho todo esto, el uso de mixins con mypy probablemente requerirá un poco más de estructura de lo que actualmente tiene. Mypy recomienda un enfoque que es básicamente lo que está describiendo deceze : crear un ABC que MyMixin clases Main y MyMixin . No me sorprendería si tuvieras que hacer algo similar para hacer feliz al corrector de Pycharm.


Resulta que mi intento original fue bastante cercano a la solución también. Esto es lo que estoy usando actualmente:

# main.py import mymixin.py class Main(object, MyMixin): def func1(self, xxx): ... # mymixin.py if False: from main import Main class MyMixin(object): def func2(self: ''Main'', xxx): # <--- note the type hint ...

Tenga en cuenta la importación dentro de la declaración if False que nunca se importa (pero el IDE lo sabe de todos modos) y el uso de la clase Main como cadena porque no se conoce en tiempo de ejecución.