Bezeichnername aus festem Präfix + String-Elementen aus einem Tupel zusammensetzen

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
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Hallo

Ich würde gerne mehrere Objekte des gleichen Typs erstellen. Der Name (Bezeichner) jedes zu erstellenden Objektes soll sich aus einem festen Präfix und String-Elementen aus einem Tupel zusammensetzen.

Etwas Python-Code zur Verdeutlichung was ich meine:

Code: Alles auswählen

from PyQt5.QtCore import QTimer


class Machine():
    def __init__(self):
        pump_names = ('water_pump, oil_pump', 'air_pump', 'grease_pump')

        self._timers = []

        for name in pump_names:
            timer = QTimer()
            timer.setSingleShot(True)
            # timer.timeout.connect(self._start_<name>) # Also `self._start_water_pump`, usw.
            # self._timers.append(self.timer_<name>) # Also `self.timer_water_pump`, usw.

    def _start_water_pump(self):
        pass

    def _start_oil_pump(self):
        pass

    def _start_air_pump(self):
        pass

    def _start_grease_pump(self):
        pass


def main():
    machine = Machine()


if __name__ == "__main__":
    main()
Am Ende sollen in der Liste `self._timers` dann 4 `QTimer`-Objekte mit folgenden Namen (Bezeichner) enthalten sein.
  • self.timer_water_pump
  • self.timer_oil_pump
  • self.timer_air_pump
  • self.timer_grease_pump
Lässt sich so etwas umsetzen?

Gruß
Atalanttore
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Atalanttore: Ja, aber ich würde da ja erst einmal fragen warum das Attribute sein müssen und warum Du das nicht einfach in ein Wörterbuch stecken kannst das die Namen auf die Timer abbildet. Also beispielsweise anstelle der Liste. Und dann nur noch eine `_start_pump()`-Methode die den Namen der Pumpe als Argument bekommt.

Edit: Als Code:

Code: Alles auswählen

#!/usr/bin/env python3
from functools import partial

from PyQt5.QtCore import QTimer


class Machine:
    def __init__(self):
        self._timers = {
            name: QTimer(
                singleShot=True, timeout=partial(self._start_pump, name)
            )
            for name in ["water", "oil", "air", "grease"]
        }

    def _start_pump(self, name):
        pass


def main():
    machine = Machine()


if __name__ == "__main__":
    main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Oder mit getattr() in etwa so:

Code: Alles auswählen

class Machine:
    def __init__(self):
        self._timers = {}
        for name in ("water", "oil", "air", "grease"):
            callback = getattr(self, f'_start_{name}_pump')
            self._timers[name] = QTimer(singleShot=True, timeout=callback)

    def _start_water_pump(self):
        pass

    def _start_oil_pump(self):
        pass

    def _start_air_pump(self):
        pass

    def _start_grease_pump(self):
        pass
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Danke für euren Code.
__blackjack__ hat geschrieben: Freitag 25. Oktober 2019, 19:43 @Atalanttore: Ja, aber ich würde da ja erst einmal fragen warum das Attribute sein müssen und warum Du das nicht einfach in ein Wörterbuch stecken kannst das die Namen auf die Timer abbildet. Also beispielsweise anstelle der Liste. Und dann nur noch eine `_start_pump()`-Methode die den Namen der Pumpe als Argument bekommt.
Natürlich könnte ich auch ein Wörterbuch nehmen, das die Namen auf die Timer abbildet. Mich würde nur interessieren, ob und wie man Bezeichner für Objekte aus Strings individuell zusammensetzen kann.

Gruß
Atalanttore
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Atalanttore hat geschrieben: Samstag 26. Oktober 2019, 12:38 Mich würde nur interessieren, ob und wie man Bezeichner für Objekte aus Strings individuell zusammensetzen kann.
Hier mal ein Beispiel.

Code: Alles auswählen

class Foo:
    def create_attribute(self, key, value):
        setattr(self, f'dynamic_{key}', value)

bar = Foo()
bar.create_attribute('baz', 42)
print(bar.dynamic_baz)
Aber wie gesagt: Tu es nicht! Genau für so etwas gibt es passende Datenstrukturen wie ein Dictionary. Im Endeffekt müsstest du ja doch wissen wie die Attribute heißen oder du baust dir die komplette Logik nach, die du mit einem Dictionary ohnehin bekommst.
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Ist die Abbildung auf ein Dictionary/Wörterbuch die pythonisch(t)e Art mehrere Objekte des gleichen Typs auf einmal zu erstellen?

Gruß
Atalanttore
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ein Dictionary ist als Datenstruktur auch in vielen anderen höheren Programmiersprachen bekannt (häufig auch Mapping genannt). Das ist keine spezielle Erfindung von Python. Auch muss man es nicht zwingend für Objekte gleicher Bauart verwenden.

Hier ist es aber sinnvoll, die Beziehung Name -> Methode darüber abzubilden. Wobei ich getattr() hier auch nicht falsch finde, falls man ohnehin auf der Klasseninstanz arbeitet...
Benutzeravatar
__blackjack__
User
Beiträge: 13068
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Die Frage bei den Attributen ist IMHO ob man da nur programmatisch drauf zugreift. Falls ja, stellt sich die Frage was da der Vorteil gegenüber einem dedizierten Wörterbuch sein soll. Denn auch die Attribute landen ja letztendlich in einem Wörterbuch (`__dict__` von dem Objekt), nur das sie sich da den Namensraum mit anderen ”Dingen” teilen. Warum macht das Sinn? Gibt es irgendwo Code wo der Programmierer tatsächlich im Quelltext über das Attribut zugreift in dem er die Namen selbst ausschreibt?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@Atalanttore: Es war zwar nicht Deine Frage, aber ich würde die Strukturierung der Anwendung kritisch betrachten. Du hast bislang keine Maschine, sondern Pumpen. Vorschlag: modelliere zunächst die Pumpen. In einer späteren Machine-Klasse könntest Du dann Pumpen als Attribute anlegen (hier beispielhaft als dict umgesetzt):

Code: Alles auswählen

from PyQt5.QtCore import QTimer


PUMP_NAMES = ('water_pump, oil_pump', 'air_pump', 'grease_pump')


class Pump:

    def __init__(self, name):
        self.name = name
        self.timer = QTimer(...)
        ...
        
    def start(self):
        pass
        
        
pumps = {name: Pump(name) for name in PUMP_NAMES}
Atalanttore
User
Beiträge: 407
Registriert: Freitag 6. August 2010, 17:03

Danke für die vielen Erklärungen.

Gruß
Atalanttore
Antworten