Meine Frage besteht darin, den "guten Weg" zu finden, eine Funktion zu definieren, deren Implementierung sich nach einem bestimmten Kriterium unterscheidet. Diese Funktion wird von mehreren Skripten aufgerufen, daher muss ich sie in ein Modul einfügen.Bedingte Definition einer Funktion in einem Modul
Zum Beispiel betrifft mein Kriterium, auf welcher Plattform das Skript ausgeführt wird, aber klar, dass der Test alles ertragen könnte. Meine Funktionen ermöglichen persistent Definition/retrieving von Umgebungsvariablen, so habe ich ein Modul namens persistenv.py nach dem folgenden Schema hergestellt (Lösung 1):
# CROSS-PLATFORM PART
def my_function1() :
# ... body1 ...
# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
def my_function2() :
# ...body2 for Windows...
# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
def my_function2() :
# ...body2 for Linux...
else :
raise ImportError('Your platform is not supported')
Die oben stellt zwei mögliche Definitionen der gleichen Funktion in einem einzigen Modul. Wie auch immer, es klang ziemlich viel sauberer mir als Testen der Plattform jedes Mal die Funktion aufgerufen wurde (Lösung 2):
# CROSS-PLATFORM PART
def my_function1() :
# ... body1 ...
def my_function2() :
# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
# ...body2 for Windows...
# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
# ...body2 for Linux...
fand ich eine andere approach, in dem jeder plattformspezifischen Teil in ein eigenes Modul extrahiert wurde, und dann bedingt in persistenv.py importiert (Lösung 3):
# CROSS-PLATFORM PART
def my_function1() :
# ... body1 ...
# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
from persistenv_win import my_function2
# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
from persistenv_linux import my_function2
else :
raise ImportError('Your platform is not supported')
Bisher erreichte ich die folgenden Schlussfolgerungen (und bekam folgende Fragen):
SOLUTION 2 sollte kaum verwendet werden, insbesondere, wenn Sie mehrere plattformspezifische Funktionen haben my_function2, my_function3, my_function4 ... (wie Sie den Test in jedem von ihnen wiederholen würde)
SOLUTION 1 erscheint ganz einfach (keine zusätzlichen Dateien, ein einzelner Test), aber ich frage mich, wie verhält sich Python (intern), wenn man "von persistenv import my_function2" aufrufen muss?
SOLUTION 3 scheint Pythonic (verwendet in integrierten Implementierungen, os.path zum Beispiel), aber kann es nicht problematisch sein, wenn persistenv.py, persistenv_win.py und persistenv_linux.py Teil eines gleichen sind Paket (neben anderen Modulen), die ich global importiere, indem ich "import my_package" im Hauptskript?
Danke für Ihre Anmerkungen. Ich nehme an, dass es keine "schmutzige Praxis" ist, eines der 3 Muster zu verwenden, es hängt nur von der Situation ab. Ihren letzten Punkt verstehe ich jedoch nicht vollständig: Ich muss mich irren, aber wenn Sie my_package importieren, laden Sie persistenv.py (das entweder persistenv_win.py oder persistenv_linux.py lädt) UND persistenv_win.py UND persistenv_linux.py, nicht unbedingt in dieser Reihenfolge. Ist jedes dieser 3 Module an einen eigenen Namensraum gebunden? (zB 'my_package.persistenv_win.my_function2()'? – gromk13
@ gromk13 Selbst wenn sie gleichzeitig geladen würden (was nicht wahr ist), hätten sie zwar ihren eigenen Namensraum, aber das Laden findet nur bei Bedarf statt, dh nur diese Module die ich explizit geladen habe, sind tatsächlich geladen. " – glglgl
Mein Fehler, ich habe fälschlicherweise angenommen, dass das Importieren eines Pakets automatisch alle seine Module importiert. Eigentlich wäre die oben beschriebene problematische Situation eher das Ergebnis von' from my_package import * ', with' __all__ = [..., 'persistenv', 'persistenv_win', 'persistenv_linux', ...] ', das wäre ein ziemlich dummer Schachzug ... – gromk13