import innerhalb der class-Anweisung

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo,

ich habe bezüglich der imports eine Frage. Bis jetzt habe ich es so kennen gelernt, dass Module und die dazugehörigen Funktionen und Klassen weit vorher importiert werden. Aber ist es "unschön" bzw ist es "Python-Unlike" wenn man ein Modul und die dazugehörigen Klassen/Funktionen innerhalt eine Klasse importiert? Um es euch zu veranschaulichen, was mir da vorschwebt:

Code: Alles auswählen

import sys  

from PyQt4.QtGui import QAction, QMenuBar, QIcon
from PyQt4.QtCore import SIGNAL, SLOT, QString

class Klasse(object):
    def __init__ (self, parent=None):
        Klasse.__init__(self, parent)

        Beispiel= "1"

        if Beispiel== "1":
            from  Ordner.Mein_Beispiel1 import MainWindow
        if Beispiel== "2":
            from  Ordner.Mein_Beispiel2 import MainWindow
# Erst wenn die Bedingung abgefragt wurde, und ein bestimmtes Modul mit
# den dazugehörigen Funktionen und Klassen importiert wurden
# folgt dann der weitere Code-Abschnitt.
Mir fiel zu aller erst selbst eine vermeintliche Lösung ein, und zwar könnte man zwei Klassen in eine py-Datei hinterlegen. So würde man den import wie üblich wieder weit am Anfang setzen und dann sähe die Geschichte wie folgt aus:

Code: Alles auswählen

import sys  

from PyQt4.QtGui import QAction, QMenuBar, QIcon
from PyQt4.QtCore import SIGNAL, SLOT, QString

from  Ordner.Mein_Beispiel import MainWindow1, MainWindow2

class Klasse(object):
    def __init__ (self, parent=None):
        Klasse.__init__(self, parent)

        Beispiel= "1"

        if Beispiel== "1":
            self.String1 = MainWindow1()
        if Beispiel== "2":
            self.String2 = MainWindow2()

Aber aus der Erfahrung heraus weiß ich, dass Quelltexte mit der Zeit immer umfangreicher werden. Von daher gewöhne ich mir jetzt in meinem Lern-Modus gleich an, die Funktionen, Klassen in andere Dateien auszulagern und sie, wenn sie gebraucht werden, zu importieren. Daher kam auch meine Idee auf, ein Modul und die dazugehörigen Klassen/Funktionen innerhalb einer Klasse zu importieren, je nach dem welche Bedingung gerade erfüllt ist. Damit ich aber nicht gleich was falsches lerne bzw. mir einen unsauberen Stil aneigne, wollte ich mal nach eurer Meinung fragen. Natürlich bin ich auch für Ratschläge offen.

Gruß
Sophus
BlackJack

@Sophus: Importe werden in aller Regel am Anfang des Moduls gemacht damit man leichter sieht wovon ein Modul abhängig ist. Dann wird die ``import``-Anweisung auch nicht jedes mal gemacht wenn ein Exemplar von `Klasse` erstellt wird.

Das ”vorsorgliche” aufteilen auf Dateien würde ich auch nicht machen. Wenn es thematisch zusammen gehört, gehört es in ein Modul. Wenn das Modul zu gross wird, kann man es später immer noch aufteilen. Oder in ein Package umwandeln und dort dann den Inhalt auf verschiedene Module aufteilen. Motivation für eine Aufteilung sollte also die Bedeutung der Funktionen und Klassen haben und wenn *tatsächlich* ein Modul zu gross wird, und nicht ein vorauseilendes „es könnte ja mal zu gross werden”. Tut es aber nicht immer und dann hat man Module die keinen Sinn machen weil sie nichts zusammenfassen. Sieht man zum Beispiel ganz gut an den vielen Modulen und Klassen im ersten Beitrag von Programm zieht viel RAM und wird langsam im Vergleich zur Lösung mit einem Modul und zwei Klassen die im Grunde das selbe machen in diesem Beitrag: Re: Programm zieht viel RAM und wird langsam.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo,

vielen Danke für den Ratschlag. Also, ich teile deswegen so "vorsorglich" auf, weil ich jetzt schon weiß, dass das Modul wirklich so groß wird. Es handelt sich hierbei um einen Versuch Sprachmodule zu erstellen. Bis jetzt habe ich German.py und und English.py. Dabei arbeite ich mit dem Dictionary. Und wenn später noch weitere Formen und Widgets hinzukommen, um so umfangreicher wird es schon in einer Sprache (z.B.: Deutsch) werden. Also will ich nicht die Sprachen in ein Modul lassen. Daher auch meine vorsorgliche Auslagerung. Meine Idee funktioniert auch wunderbar. Bis jetzt habe ich auch erstmal nur ein Fenster, und zwar QMainWindow. Dieses Fenster erzeuge ich auch per Hand, sprich selbst geschriebener Code. Ich will soweit wie es geht die Finger vom Qt-Designer lassen. Ich weiß auch, dass es einen Qt-Linguist gibt. Aber ich dachte, ich baue mal selbst ein eigenes Sprachmodul. Und anhand des Beispiel soll also abgefragt, welche Sprache der Benutzer sich wünscht, und dementsprechend wird sein Modul importiert. Das sieht folgendermaßen aus. Beim Laden des Programm soll die INI-Datei geöffnet werden, es wird nachgeschaut welcher Wert zum Schlüssel dort steht (Beispiel Language = English), dieser Wert wird dann in eine Variable geschrieben, und anschließend in einer If-Schleife dann abgefragt. Steht in der Variable nun das Wort "English", so soll die Klasse aus dem Modul English.py geladen werden.

Klappt alles tadellos. Aber als ich den Import der Sprachdatei in die Klasse verlegt habe, war ich mir nicht sicher, ob ich es richtig mache, also im Sinne von Python. Wie gesagt, klappen tut es wunderbar.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Ein Import in einer Methode, würde ich nur dann machen, wenn es einen wichtigen Grund dafür gibt.
Z.B. wenn Du im Modul Initialisierungen machst, die nicht so ohne weiteres laufen. Das kann bei Qt Anwendungen passieren, da geht einiges erst, wenn der Qt-Event-Thread läuft.

Wenn Du einfach nur den gleichen Klassennamen in zwei Modulen hast, dann kanst Du das auch so machen:

Code: Alles auswählen

from  Ordner.Mein_Beispiel1 import MainWindow as MainWindow1
from  Ordner.Mein_Beispiel2 import MainWindow as MainWindow2
Was ich auch gerne mache ist optionale Module so zu importieren

Code: Alles auswählen

try:
    import setproctitle
    setproctitle.setproctitle("mein-Programm") # dann steht unter Unix wenn man "top" aufruft nicht einfach python, sondern "mein-Programm"
except ImportError:
    pass # dann eben nicht
a fool with a tool is still a fool, www.magben.de, YouTube
BlackJack

@Sophus: Warum genau willst Du so ein kompliziertes Rad neu erfinden? Da gibt es schon eine Lösung für.

Edit: http://if-schleife.de/
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Sophus: Wenn das Design des Hauptfensters aufgrund einer bestimmten Bedingung unterschiedlich ist, dann würde ich gemeinsame Funktionalität innerhalb einer Klasse ``BaseMainWindow`` (oder anderem Namen) definieren und die spezialisierten Klassen davon erben lassen. Mit einer Hilfsfunktion ``get_main_window(condition)`` (wobei ``condition`` sehr abstrakt ist, aber bisher hast du ja nichts detailliertes zu der Bedingung geschrieben) kann man sich dann die passende Klasse an einer beliebigen Stelle im benutzenden Code liefern lassen, ohne dass man dort einen bedingten Import einbauen müsste.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo,

damit es nicht zu sehr abstrakt wird, erstelle ich meinen verkürzten Code da. Ich zeuge es euch erstmal mit dem Beispiel der Menuleiste. Da ich mit meiner ToolBar so ähnlich verfahre, denke ich, brauche ich das nicht nochmal extra zu demonstrieren. Wie ihr seht, werde ich im Modul MDIForm_Menue.py abfragen, welche Sprache der Benutzer eingestellt hat, indem ich die Werte aus der INI-Datei lade. Das Laden der Werte aus der INI-Datei werde ich mit einem weiteren Modul machen (Config.py). In dieses Modul werde ich alle Einstellungen aus der INI-Datei in die Dictionary des Moduls Config.py laden. Und dieses Modul werde ich auch einbinden, und abfragen, welche Sprache nun verwendet wird. Und in meinem Fall habe ich keine andere Idee, außer die Importe der Module innerhalb der Klasse zu verorten.

MDIForm.py (Mein Hauptfenster)

Code: Alles auswählen

import sys  

from PyQt4.QtGui import QMainWindow, QApplication, QAction, QMenuBar, QToolBar, QIcon, QMdiArea, QScrollBar
from PyQt4.QtCore import SIGNAL, SLOT, Qt

from MDIForm_Menue import MainWindow_MenuBar
from MDIForm_ToolBar import ToolBar_Manage, ToolBar_Close
from  Info import Information
class MDIFormular(QMainWindow):
    # Vererbung aktivieren, angeben, dass es keine Elternform hat
    def __init__ (self, parent=None): 
        QMainWindow.__init__(self, parent)
        
        self.setWindowIcon(QIcon('Xarphus/Images/16x16/world1.png'))
        self.statusBar().showMessage('Ready')

        self.MNUL_Verwaltung = MainWindow_MenuBar() # Menuleiste wird in die Klasse MDIFormular hinzugefügt
        self.setMenuBar(self.MNUL_Verwaltung)

        self.Info_Program = Information() # Die Klasse "Information" in die Klasse "MenueLeiste" einbinden

        [...]
        
        self.DoShowToolBar = ToolBar_Manage()
        self.addToolBar(self.DoShowToolBar)

if __name__ == "__main__":
    print 'Dieses Programm läuft als Main.'
else:
    print 'Das Programm wird von einem anderen Modul importiert.'

app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DontShowIconsInMenus, False)
MDIWindow = MDIFormular()
MDIWindow.showMaximized()
sys.exit(app.exec_())
MDIForm_Menue.py (Hier habe ich besonders darauf geachtet, dass in beiden Modulen - English.py und German.py - die Klassen gleiche Namen haben: Language. So muss ich nicht viel Code-Schnippel basteln)

Code: Alles auswählen

# -*- coding: utf-8 -*-
import sys  

from PyQt4.QtGui import QAction, QMenuBar, QIcon, QPixmap
from PyQt4.QtCore import SIGNAL, SLOT, QString 

class MainWindow_MenuBar(QMenuBar):
    def __init__ (self, parent=None):
        QMenuBar.__init__(self, parent)

        
        SprachWahl = "German"

        if SprachWahl == "German":
            from  Language.German import Language
        if SprachWahl == "English":
            from  Language.English import Language 
    
        self.MenuBar_Dict_Language = Language() # Die Klasse "LanguageGerman" in die Klasse "MenueLeiste" einbinden
        self.Info_Program = Information()

        ########################################################################
        ###### Menuleiste (=MNUL) "Verwaltung" ###########################################
        ########################################################################
        # Eine eigenständige Menuleiste wird erstellt. 
        self.menuManage = self.addMenu(self.MenuBar_Dict_Language.Dict_MenuBar["menuManage"])

        # Menüpunk
        self.DoShowmnuFilm = self.menuManage.addMenu((self.MenuBar_Dict_Language.Dict_MenuBar["menuMovie"]))
        # Untermenü
        self.FilmAdd = self.DoShowmnuFilm.addAction((self.MenuBar_Dict_Language.Dict_MenuBar["menuAddMovie"]))     
        
        self.FilmAdd.setStatusTip(self.MenuBar_Dict_Language.Dict_MenuBar["menuAddMovie"])
        self.FilmAdd.setShortcut("Ctrl+F")
        
        self.SerieAdd = self.DoShowmnuFilm.addAction((self.MenuBar_Dict_Language.Dict_MenuBar["menuAddSerie"]))
        self.SerieAdd.setStatusTip(self.MenuBar_Dict_Language.Dict_MenuBar["menuAddSerie"])
        self.SerieAdd.setShortcut("Ctrl+S")
        [...]
German.py

Code: Alles auswählen

# -*- coding: cp1252 -*-
class Language(object):

###############################
####### MDIForm ###############
###############################
# Nur die Menuleiste und die StatusbarTip
        Dict_MenuBar = { 
                      "menuManage" : "Verwaltung", 
                      "menuMovie" : "Filme",
                      "menuAddMovie" : "Film hinzufügen", 
                      "menuAddSerie" : "Serie hinzufügen",
                      [...]                       
                        }
English.py

Code: Alles auswählen

# -*- coding: cp1252 -*-
class Language(object):

###############################
####### MDIForm ###############
###############################
# Nur die Menuleiste und die StatusbarTip
        Dict_MenuBar = { 
                      "menuManage" : "Manage", 
                      "menuMovie" : "Movie",
                      "menuAddMovie" : "Add Movie", 
                      "menuAddSerie" : "Add Serie",
                      [...]                       
                        }
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

In PyQt ist die Mehrsprachigkeit schon eingebaut:
http://pyqt.sourceforge.net/Docs/PyQt4/i18n.html

Du programmierst Deine Anwendung nur in einer Sprache. Alle Texte setzt Du in tr("...")

Code: Alles auswählen

print( QObject.tr("Hallo Welt") )
Dann lässt Du PyQt Deinen Code analysieren, PyQt sammelt alle Strings die in tr("...") stehen ein und macht Resourcen-Dateien daraus. Für jede zusätzliche Sprache musst Du nun alle diese Texte in einer weiteren Resourcendatei übersetzen (von PyQt Toolunterstützt).

Frag mich nicht wie die PyQt Tools heißen die das machen, die benutzt ein anderer im Team, ich klammere einfach nur alle zu übersetzenden Texte mit tr("...") ein.
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

MagBen hat geschrieben:In PyQt ist die Mehrsprachigkeit schon eingebaut:
http://pyqt.sourceforge.net/Docs/PyQt4/i18n.html

Du programmierst Deine Anwendung nur in einer Sprache. Alle Texte setzt Du in tr("...")

Code: Alles auswählen

print( QObject.tr("Hallo Welt") )
Dann lässt Du PyQt Deinen Code analysieren, PyQt sammelt alle Strings die in tr("...") stehen ein und macht Resourcen-Dateien daraus. Für jede zusätzliche Sprache musst Du nun alle diese Texte in einer weiteren Resourcendatei übersetzen (von PyQt Toolunterstützt).

Frag mich nicht wie die PyQt Tools heißen die das machen, die benutzt ein anderer im Team, ich klammere einfach nur alle zu übersetzenden Texte mit tr("...") ein.
Hallo,

darf ich fragen, was denn daran falsch sei, wenn man sein eigenes Sprachmodul erstellt?
BlackJack

@Sophus: Es gibt einen funktionierenden Standardweg den viele Programmierer und Übersetzer kennen. Da etwas eigenes erfinden zu wollen ist auf jeden Fall nicht richtig.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Es gibt einen funktionierenden Standardweg den viele Programmierer und Übersetzer kennen. Da etwas eigenes erfinden zu wollen ist auf jeden Fall nicht richtig.
Ich denke, es gibt hier weder falsch noch richtig. Nennen wir es einfach "ungewöhnlich" :-)
BlackJack

Laut Zen of Python wäre ungewöhnlich aber schon irgendwie falsch.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Man sollte doch zumindest alle Sprachen in *eine* Datei a la "language.py" stecken können. Und da kann man dann - wie ich schon in anderer Form vorgeschlagen hatte - mittels ``get_language(name)`` die passende Klasse oder Klasseninstanz erzeugen lassen. Ich schließe mich aber meinen Vorrednern an, dass die Einarbeitung in das von Qt bereitgestellte Verfahren die deutlich bessere Idee ist. Zumal die "po"-Dateien auch Standard außerhalb von Qt sind.
BlackJack

Um noch mal das Wort Standard hervorzuheben, ausserhalb von Qt werden diese Dateien von der gettext-API benutzt und für *die* gibt es in der Python-*Standard*bibliothek das Modul `gettext`.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

snafu hat geschrieben:Man sollte doch zumindest alle Sprachen in *eine* Datei a la "language.py" stecken können. Und da kann man dann - wie ich schon in anderer Form vorgeschlagen hatte - mittels ``get_language(name)`` die passende Klasse oder Klasseninstanz erzeugen lassen. Ich schließe mich aber meinen Vorrednern an, dass die Einarbeitung in das von Qt bereitgestellte Verfahren die deutlich bessere Idee ist. Zumal die "po"-Dateien auch Standard außerhalb von Qt sind.
Standard hin und Standard her. Versteht mich nicht falsch, es klingt ja immer so toll, wenn man das Wort Standard benutzt. Aber mir wird immer noch nicht richtig klar, was an meiner Vorgehensweise nicht korrekt sein soll? Und jetzt lasst mal das Wort Standard an dieser Stelle beiseite, denn ich habe es längst verstanden, dass es nicht dem Standard entspricht. Ich liste mal meine für mich klar definierte Vorteile auf. Ersten muss ich mich nicht mit diesem PyQt-Tool herumschlagen, indem ich alle Strings einlesen lassen muss, sie womöglich mit Qt-Linguist noch bearbeiten muss und und und und.... bei meinem Weg erstelle ich eine einfache .py-Datei und jeder könnte sie leicht modifizieren. Ich weiß nicht wie eine .po-Datei aussieht wenn man sie mit einem Texteditor öffnet, bestimmt eher wie eine XML-Datei, wo kein Mensch außerhalb der Programmierwelt nicht sofort durchsteigt. Es mag auch möglich sein, dass man durch die PyQt-Tools etwas schneller ist mit der Übersetzung, jedoch stellt es für mich kein Problem dar.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Sophus: Irrtum. Du befasst dich nicht ernsthaft mit der Gegenargumentation, weil du sie mehr oder weniger als für dich irrelevant bezeichnest. Wenn du also von vornherein allgemein anerkannte Argumente abweist, dann wird es schwer, dir noch weitere Argumente zu liefern. Mach halt dein Ding. Davon wird dich wohl sowieso keiner abhalten können...
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

snafu hat geschrieben:@Sophus: Irrtum. Du befasst dich nicht ernsthaft mit der Gegenargumentation, weil du sie mehr oder weniger als für dich irrelevant bezeichnest. Wenn du also von vornherein allgemein anerkannte Argumente abweist, dann wird es schwer, dir noch weitere Argumente zu liefern. Mach halt dein Ding. Davon wird dich wohl sowieso keiner abhalten können...
Es ist kein Argument zu sagen "Ja, weil, ist eben so, wegen Standard". Mag vielleicht unter euch allgemein anerkannt sein, aber für mich reicht es nicht. Ich lehne nichts von vornherein ab. Ich erinnere mich noch, als ich im ersten Semester in einer Veranstaltung saß, wo uns das Werkzeug für wissenschaftliches Arbeiten in die Hand gedrückt wurde. Nur weil eben alles Standard ist, habe ich es nicht einfach übernommen, ich beging einiges zu hinterfragen. Erst als die Dozenten davon weggingen mit ihrem "Ja weil wegen Standard" und mir erklärten, warum man bei wissenschaftlichen Arbeiten das und dies berücksichtigen muss, wieso beim Bibliographieren das Komma dort sitzen muss, und nicht da, und das der Doppelpunkt da sitzen muss etc, und wieso es in der Fußnote so aussehen muss und blah. Einiges stelle ich nach wie vor in Frage, aber das meiste an Werkzeugen habe ich übernommen, eben nicht weil man mir bloß sagte, "Ja weil wegen Standard", sondern weil es für mich nachvollziehbar geworden ist und ich merkte, dass es kein verkehrter Weg ist. Überzeugungsarbeiten nennt man das. Es ist leicht zu sagen "Du machst das weil es Standard ist, keine Widerworte". Ich will mich gegen nichts wehren, aber wenn für mich nichts nachvollziehbares kommt, dann wirkt es eher bei mir so aufgezwungen, so nach dem Motto "Andere machen das auch so, also machst du das auch so, damit wir alle das gleiche machen". Was erkaufe ich mir an meiner Vorgehensweise für Nachteile? Meine Sprachdatei ist ohne Umwege modifizierbar, erweiterbar und leicht zu pflegen. Und zu sagen "Ja weil wegen Standard" ist kein Argument, auch wenn es so aussieht. Es ist höchstens ein Teil-Argument, wenn überhaupt.
BlackJack

@Sophus: Natürlich ist Standard ein Argument. Standard bedeutet das hat sich über die Zeit als eine gute Lösung etabliert. Das ist ja nicht Standard weil das von irgendeiner Instanz vorgeschrieben wird. Wenn etwas besseres daher kommt, dann wird sich *das* als Standard durchsetzen. Standard bedeutet man lernt etwas was man an anderer Stelle auch verwenden kann, und man verwendet etwas was andere auch kennen.

Alleine *das* es etwas gibt, ist schon ein Grund nicht selber etwas zu erfinden, solange das nicht *besser* ist. Solange Du die vorhandene Lösung aber gar nicht kennst, kannst Du das nicht einschätzen.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich bin froh, dass es bei Steckdosen einen Standard gibt und hätte ich meinen Elektriker gefragt, warum er beim Stromanschluss nicht Wechselstrom mit 70Hz und 166V einspeisen kann, hätte er auch nur geantwortet, dass das eben nicht Standard ist.
Was ist Deiner Meinung nach bei Internationalisierungslösungen so schlecht gelöst, dass es den Aufwand lohnt, etwas eigenes zu erfinden?
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@Sophus: Wenn du dich *ernsthaft* mit dem Gegenargument beschäftigen möchtest, dann recherchiere doch mal selbst zu dem Thema "po"-Dateien / Internationalisierung. Ich werde dir hier nichts vorkauen, was an anderen Stellen viel besser beschrieben wird als ich es wiedergeben könnte. Wenn dir die Eigenrecherche zu mühsam ist, dann schlage den Tipp halt in den Wind. Ich will dir hier nichts aufzwingen oder dich mit irgendwas bekehren.
Antworten