Ich versuche meine große Klasse in zwei Teile zu teilen. Nun, im Grunde in die "Haupt" -Klasse und ein Mixin mit zusätzlichen Funktionen, wie so:
main.py
Datei:
import mymixin.py
class Main(object, MyMixin):
def func1(self, xxx):
...
mymixin.py
Datei:
class MyMixin(object):
def func2(self: Main, xxx): # <--- note the type hint
...
Nun, obwohl dies gut funktioniert, kann der Typhinweis MyMixin.func2
natürlich nicht funktionieren. Ich kann nicht importieren main.py
, da ich einen zyklischen Import erhalten würde und mein Editor (PyCharm) ohne den Hinweis nicht sagen kann, was self
ist.
Ich verwende Python 3.4 und bin bereit, auf 3.5 umzusteigen, wenn dort eine Lösung verfügbar ist.
Gibt es eine Möglichkeit, meine Klasse in zwei Dateien aufzuteilen und alle "Verbindungen" beizubehalten, sodass meine IDE mir weiterhin die automatische Vervollständigung und alle anderen Extras bietet, die daraus entstehen, wenn ich die Typen kenne?
self
, da es immer eine Unterklasse der aktuellen Klasse sein wird (und jedes Typprüfsystem sollte in der Lage sein, dies selbst herauszufinden). Wirdfunc2
versucht, Anruffunc1
, der nicht in definiert istMyMixin
? Vielleicht sollte es sein (alsabstractmethod
, vielleicht)?class Main(MyMixin, SomeBaseClass)
damit Methoden aus der spezifischeren Klasse diejenigen aus der BasisklasseAntworten:
Ich fürchte, es gibt keine äußerst elegante Möglichkeit, Importzyklen im Allgemeinen zu handhaben. Sie können entweder Ihren Code neu gestalten, um die zyklische Abhängigkeit zu entfernen, oder, wenn dies nicht möglich ist, Folgendes tun:
Die
TYPE_CHECKING
Konstante ist immerFalse
zur Laufzeit, daher wird der Import nicht ausgewertet, aber mypy (und andere Tools zur Typprüfung) werten den Inhalt dieses Blocks aus.Wir müssen auch das machen
Main
Typanmerkung auch in eine Zeichenfolge umwandeln und sie effektiv weiterleiten, da dasMain
Symbol zur Laufzeit nicht verfügbar ist.Wenn Sie Python 3.7+ verwenden, können wir zumindest die Bereitstellung einer expliziten Zeichenfolgenanmerkung überspringen, indem wir PEP 563 nutzen :
Das
from __future__ import annotations
Import werden alle Typhinweise zu Zeichenfolgen und überspringen die Auswertung. Dies kann dazu beitragen, unseren Code hier etwas ergonomischer zu gestalten.Alles in allem erfordert die Verwendung von Mixins mit mypy wahrscheinlich etwas mehr Struktur als derzeit. Mypy empfiehlt einen Ansatz , der im Grunde genommen
deceze
beschreibt - ein ABC zu erstellen, das sowohl SieMain
als auch IhreMyMixin
Klassen erben. Es würde mich nicht wundern, wenn Sie etwas Ähnliches tun müssten, um Pycharms Kontrolleur glücklich zu machen.quelle
typing
, aber PyCharm war auch ziemlich zufrieden damitif False:
.__init__
typing. TYPE_CHECKING
: python.org/dev/peps/pep-0484/#runtime-or-type-checkingFür Personen, die mit zyklischen Importen zu kämpfen haben, wenn sie eine Klasse nur zur Typprüfung importieren: Sie möchten wahrscheinlich eine Weiterleitungsreferenz verwenden (PEP 484 - Typhinweise):
Also statt:
Sie machen:
quelle
File -> Invalidate Caches
?if False:
dir kannst du auchfrom typing import TYPE_CHECKING
undif TYPE_CHECKING:
.Das größere Problem ist, dass Ihre Typen zunächst nicht gesund sind.
MyMixin
macht eine fest codierte Annahme, dass es eingemischt wirdMain
in eine beliebige Anzahl anderer Klassen eingemischt wird, in welchem Fall es wahrscheinlich brechen würde. Wenn Ihr Mixin fest codiert ist, um in eine bestimmte Klasse gemischt zu werden, können Sie die Methoden auch direkt in diese Klasse schreiben, anstatt sie zu trennen.Um dies mit vernünftiger Typisierung richtig zu tun,
MyMixin
sollte es gegen eine Schnittstelle oder eine abstrakte Klasse im Python-Sprachgebrauch codiert werden :quelle
Es stellte sich heraus, dass mein ursprünglicher Versuch auch der Lösung ziemlich nahe kam. Folgendes verwende ich derzeit:
Beachten Sie den Import innerhalb der
if False
Anweisung, der nie importiert wird (aber IDE weiß es trotzdem), und verwenden Sie dieMain
Klasse als Zeichenfolge, da sie zur Laufzeit nicht bekannt ist.quelle
Ich denke, der perfekte Weg sollte sein, alle Klassen und Abhängigkeiten in eine Datei (wie
__init__.py
) und dannfrom __init__ import *
in alle anderen Dateien zu importieren.In diesem Fall bist du
quelle
import *
, und dennoch können Sie diesen einfachen Ansatz nutzen