Doppelte Ausgabe?

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.
Antworten
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

jo leudde
nach langer zeit melde ich mich mal wieder mit einem neuen problem.
und zwar habe ich mich jetzt mit oop beschäftigt, und finde es viiiiiieeeel besser, als diese von oben nach unten geschreibe, wie ichs vorher gemacht hab :x
JETZT NICHT MEHR :lol:

hab aber in meinem code das problem, daß ich nicht weiß, warum ich immer zwei ausgaben erhalte???

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'DMD-OL'


class Benutzer(object):

    running = True

    def __init__(self, ident, name):
        self.id = ident
        self.name = name

    def printer(self):
        print ("Benutzer: " + str(self.id) + ", " + self.name)


class Produktpflege(Benutzer):
    def __init__(self, ident, name):
        super(Produktpflege, self).__init__(ident, name)

    def printer(self):
        print ("Benutzer: " + str(self.id) + ", " + self.name)


benutzer = Benutzer(0, "Christian")
pflege = Produktpflege(1, "Daniel")

print (benutzer.printer())
# print (pflege.printer())
# print (pflege.running)
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

schau dir mal die kleinen Änderungen an, die ich gemacht habe

Code: Alles auswählen

class Benutzer(object):

    running = True

    def __init__(self, ident, name):
        self.id = ident
        self.name = name

    def printer(self):
        return f"Benutzer: {self.id}, {self.name}"

class Produktpflege(Benutzer):
    def __init__(self, ident, name):
        super(Produktpflege, self).__init__(ident, name)

    def printer(self):
        print ("Benutzer: " + str(self.id) + ", " + self.name)

benutzer = Benutzer(0, "Christian")
pflege = Produktpflege(1, "Daniel")

print(benutzer.printer())
pflege.printer()
print (pflege.running)
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

herzlichen dank.
oh man, den 'return'-befehl, den gibs ja auch noch.
habs jetzt so:
return "Benutzer: {}, {}".format(self.id, self.name) und print (pflege.printer())
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OL: was meinst Du mit "zwei Ausgaben"? Du hast einmal die Ausgabe in `printer` und einmal die Ausgabe des Rückgabewertes `None`. Du willst wahrscheinlich nicht das `None`, dann gib es einfach nicht aus.

Besser ist es sowieso, keine Printer-Methode zu haben, sondern eine __str__-Methode:

Code: Alles auswählen

#!/usr/bin/env python
from __future__ import print_function

class Benutzer(object):
    def __init__(self, ident, name):
        self.id = ident
        self.name = name

    def __str__(self):
        return "Benutzer: {}, {}".format(self.id, self.name)


class Produktpflege(Benutzer):
    pass


benutzer = Benutzer(0, "Christian")
pflege = Produktpflege(1, "Daniel")

print(benutzer)
Wenn Du Python2 benutzt, braucht `print` keine Klammern, außer Du machst den __future__-Import, wie in meinem Beispiel.
Was soll das Klassenattribut `running`? Sieht für mich nach einem Fehler aus, denn Klassenattribute sind selten sinnvoll.
Was auch seltsam ist, ist dass eine Produktpflege ein Benutzer ist. Macht nicht eher ein Benutzer eine Produktpflege?


@ThomasL: DMD-OL benutzt offensichtlich Python2, da ist es wenig hilfreich f-Strings zu benutzen.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Sirius3 hat geschrieben: Montag 23. Juli 2018, 13:48 @ThomasL: DMD-OL benutzt offensichtlich Python2, da ist es wenig hilfreich f-Strings zu benutzen.
Woran an seinem ersten Code hätte ich das erkennen können?
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@ThomasL: an den ersten beiden Zeilen.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Danke, wieder was dazu gelernt.

"The default encoding for python3 code is utf-8. See python's unicode support.
If you want to support python2.x in the same file or if you want to use a coding other than utf-8, you need that comment."
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

jawohl 2.7.10 heißt mein baby!
und weiter gehts!
ich habe noch eine aufgabe für euch. der gewinner darf sich was aussuchen :roll:
ich versuche der klasse Produktpflege den wert running aus der Klasse Benutzer zu geben, damit ich später per knopfdruck den prozess in Produktpflege beenden kann mit self.running = False.
Hab aber grad noch etwas anderes.
wieso werden im tkinter fenster bei jedem klick beide buttons verdoppelt :lol: ???

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'DMD-OL'

from Tkinter import Tk, Button, Frame


class Benutzer(object, Frame):

    running = True

    def __init__(self, ident, name, master=None):
        self.id = ident
        self.name = name

        Frame.__init__(self, master)
        self.pack()

        self.START = Button(self)
        self.START["text"] = "START",
        self.START["width"] = 15
        self.START["command"] = self.start
        self.START.pack()

        self.QUIT = Button(self)
        self.QUIT["text"] = "QUIT"
        self.QUIT["fg"] = "red"
        self.QUIT["width"] = 15
        self.QUIT["command"] = self.quiter
        self.QUIT.pack()

    def start(self):
        print "Benutzer: {}, {}".format(self.id, self.name)
        produkt = Produktpflege(1, "TESTER")        # <--- Meine Problemzeile
        print (produkt.printer())

    def quiter(self):
        print("Closed!")
        self.quit()


class Produktpflege(Benutzer):
    def __init__(self, ident, name):
        super(Produktpflege, self).__init__(ident, name)

    def printer(self):
        return "Produktpflege: {}, {}".format(self.id, self.name)


root = Tk()
benutzer = Benutzer(0, "Christian", master= root)
benutzer.mainloop()
Benutzeravatar
__blackjack__
User
Beiträge: 13112
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@DMD-OL: Irgendwie bist Du auf fast nichts eingegangen. Variablen auf Klassenebene sind im Grunde genau das gleiche wie Variablen auf Modulebene: globaler Zustand den man nicht haben möchte. Das `running` gehört nicht auf die Klasse.

Von `object` *und* `Frame` zu erben macht keinen Sinn. Jetzt hätte ich fast gesagt weil `Frame` ja auch schon von `object` erbt, aber in diesem Fall stimmt das noch nicht einmal weil die ganzen Klassen in `Tkinter` ”old style”-Klassen sind. Ich weiss gar nicht ob sich das überhaupt verträgt die so zu mischen. Ich würde es nicht machen. Dementsprechend ist auch `super()` keine gute Idee, denn dieses Sprachkonstrukt ist für „new style“-Klassen. Wenn das alles solche Klassen wären, *muss* man übrigens auch die `__init__()` von `object` per `super()` aufrufen, sonst kann es Probleme geben.

Und Sirius hatte ja schon die Vererbungsbeziehung zwischen Benutzer und Produktpflege in Frage gestellt. Das wird dadurch das ein Benutzer ein `Frame` sein soll, noch schräger und ist ziemlich sicher falsch. Oder die Namen sind total falsch gewählt.

`quitter` würde man mit zwei t schreiben, aber das ist genau so wenig ein guter Methodenname wie `printer`. Methoden benennt man genau wie Funktionen nach den Tätigkeiten die sie durchführen. Abbrecher und Drucker sind aber keine Tätigkeiten. Die bereits auf Widgets vorhandene Methode heisst ja auch `quit()`.

Die `printer()`-Methode sollte wie von Sirius3 vorgeschlagen die `__str__()`-Methode sein.

Das mit dem verdoppeln der GUI-Elemente passiert wegen der unsinnigen Vererbungsbeziehung, die `Produktpflege.__init__()` ruft ja noch mal die `Benutzer.__init__()` auf weil `Produktpflege` ja ein Benutzer ist und ein Benutzer ein `Frame` ist. Was so überhaupt gar keinen Sinn ergibt.

Der `Benutzer` sollte sich übrigens auch nicht selbst mit `pack()` im Elternwidget anordnen, denn das nimmt dem Programmierer die Freiheit zu entscheiden wie er diese Elemente in die GUI integrieren will. Kein Widget aus `Tkinter` macht das selbst, das kann man immer von aussen entscheiden.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
DMD-OL
User
Beiträge: 315
Registriert: Samstag 26. Dezember 2015, 16:21

hi
hab so gut es geht eure verbesserungen einzubauen und habs jetzt auch zum laufen bekommen.
nur hab ich nicht rausfinden können, wie man widgets in tkinter mit place (oder grid) anordnen.
da würde ich mich über hilfe freuen.
ich hoffe es ist so jedenfalls besser...

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'DMD-OL'

from Tkinter import Tk, Frame, Label, Button


class Produktpflege:

    def __init__(self, ident, name):
        self.id = ident
        self.name = name

    def run(self):
        return "Benutzer: {}, {}".format(str(self.id), self.name)


class Benutzer(Frame, Produktpflege):

    def __init__(self, ident, name, master=None):
        self.id = ident
        self.name = name

        self.FRAME = Frame.__init__(self, master)
        self.pack()

        self.TEXT = Label(self)
        self.TEXT["text"] = "Hello world!"
        self.TEXT.pack()

        self.START = Button(self)
        self.START["text"] = "START"
        self.START["fg"] = "blue"
        self.START["width"] = 15
        self.START["command"] = self.run
        self.START.pack()

        self.QUIT = Button(self)
        self.QUIT["text"] = "SCHLIESSEN"
        self.QUIT["fg"] = "red"
        self.QUIT["width"] = 15
        self.QUIT["command"] = self.close
        self.QUIT.pack()

    def run(self):
        print("Programm gestartet...!")
        print "Benutzer: {}, {}".format(str(self.id), self.name)
        produkt = Produktpflege(1, "Daniel")
        print produkt.run()

    def close(self):
        print("Closed!")
        self.quit()


root = Tk()
benutzer = Benutzer(0, "Christian", master=root)
benutzer.mainloop()
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@DMD-OL: kannst Du mal Dein Objektmodell erklären? Warum ist jetzt ein Benutzer eine Produktpflege. Das ergibt für mich immer noch keinen Sinn und da Du das scheinbar beliebig tauschen kannst, hast Du selbst noch nicht verstanden, welchen Zweck Vererbung hat.

Warum heißt es jetzt Produktpflege.run und immer noch nicht __str__? Der Aufruf von `str´ bei .format ist unnötig, weil das implizit passiert.

self.FRAME ist quatsch, weil __init__ nichts zurückliefert. Ein Frameobjekt sollte sich immer noch nicht selbst layouten. Das muß die Stelle machen, die `Benutzer` erzeugt. Komplett großgeschriebene Variablen/Attribute sind Konstanten, was bei allen Deinen Attributen nicht der Fall ist. Statt die Optionen von Label oder Button danach zu setzen, kann man sie direkt beim Erzeugen angeben.
Antworten