neue Variablen in Schleife erstellen (?)

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
SteveGameDE
User
Beiträge: 3
Registriert: Sonntag 28. Dezember 2014, 12:30

Hallo,

für ein kleines Projekt möchte ich in einer Schleife Variablen erstellen, deren Name immer aus einem Wort wie z.B. "Variable" und der Zahl "i" aus der Schleife besteht. So sieht mein Ansatz in vereinfachter Form zurzeit aus:

Code: Alles auswählen

while True:
     i + 1
     "Variable" + i = "VariablenInhalt"
Daraus möchte ich dann fortlaufend die Variabeln "Variable1", "Variable2", "Variable3" und so weiter haben...

Ich habe das Problem schon in einigen anderen Projekten gehabt, aber dann immer es auf die Weise gelöst, dass ich die Variablen immer vorher per Hand erstellt habe, was in meinem aktuellen Fall unmöglich ist... :(

Gibt es da ne einfache Möglichkeit, das zu verwirklichen??? :?: :?: :?:
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo und willkommen im Forum!

Namen zu nummerieren ist keine gute Idee. Wenn du auf einen solchen Fall triffst, dann musst du die richtige Datenstruktur wählen. In deinem Fall bieten sich Listen an, da kannst du beliebig viele Elemente einfügen und per Index auf sie zugreifen.
Das Leben ist wie ein Tennisball.
SteveGameDE
User
Beiträge: 3
Registriert: Sonntag 28. Dezember 2014, 12:30

Danke für die schnelle Antwort!

Über Listen habe ich mich schon informiert, aber trotzdem nicht kapiert, wie ich damit umgehe. Soweit ich weiß, kann ich so eine Liste doch in eine externe Datei schreiben, oder?
Könnte ich dementsprechend auch mit anderen Python-Programmen darauf zugreifen, also neue Daten reinschreiben, die dann von meinem aktuellen Programm gelesen werden???
Und wie kann ich eine konstante Abfrage machen, ob ein Wert der Liste mit einer anderen aktuellen Variable übereinstimmt?

Könntest du/könnte mir jemand ein Beispielscript geben? (Ich bin schon mehrere Stunden an Listen verzweifelt... :D )
Benutzeravatar
pixewakb
User
Beiträge: 1412
Registriert: Sonntag 24. April 2011, 19:43

Dein Beispielcode ist Kappes.

Code: Alles auswählen

while True:                                             # 1
     i + 1                                              # 2
     "Variable" + i = "VariablenInhalt"                 # 3 
Zeile 1 produziert eine Endlosschleife, wobei ich nicht weiß, wie du dort wieder herauskommen willst. Zeile 2 addiert zu i eine 1 ohne das Ergebnis wieder in der Variable zu speichern und spätestens Zeile 3 produziert einen Fehler ("SyntaxError: can't assign to operator").

Mal eine lauffähige Variante mit einem Wörterbuch, weil ich denke, dass das ist, was du eigentlich suchst.

Code: Alles auswählen

>>> i = 0
>>> wb = {}
>>> for i in range(10):
	wb[i] = i * i

	
>>> wb[0]
0
>>> wb[1]
1
>>> wb[5]
25
>>> wb[8]
64
>>> wb[10]
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    wb[10]
KeyError: 10
>>> 
Ich sage das ungern, aber du wirst dich im Tutorial mit den Grundlagen (speziell Listen und Wörterbücher) befassen müssen. Ich habe ein Wörterbuch verwendet, weil es m. E. auf dein Problem passt. Die Zahl in eckigen Klammern ist ein Schlüssel, die Ausgabe ist der hinterlegte Wert, also in deinem Fall der "VariablenInhalt". Ein Schlüssel kann in einem Wörterbuch nur einmal vorkommen, d. h. eine neue Wertzuweisung überschreibt den vorhandenen Wert. Vielleicht kommst du damit bereits etwas weiter.
SteveGameDE
User
Beiträge: 3
Registriert: Sonntag 28. Dezember 2014, 12:30

Danke, das hat mir grade SEHR geholfen :)

Mein Programm scheint soweit zu funktionieren, jedoch habe ich das Problem, dass ich nicht weiß, ob/wie es möglich ist, alle "wb's" in einer einzigen if-Abfrage mit einer bestimmten Variable abzugleichen - geschweige denn, dass ich es überhaupt richtig eingebaut habe...
Also, mal zu meinem Projekt: ich möchte einen "Wecker" Programmieren, der aus einer Datei die Zeiten liest, die er abfragen soll...
so sieht es im Moment aus: (und ja, es ist allem in allem noch nicht perfekt, mir geht es jetzt nur um die Abfrage)

Code: Alles auswählen

from time import *
import os
import time

Weckerzahl = 1
wb = {}


while True:
	file = open('Times.txt', 'r')
	line = file.read()
	for line in file:
		wb[Weckerzahl] = line.rstrip()
		Weckerzahl + 1
	os.system('clear')
	time.sleep(0.5)
	lt = localtime()	
	print strftime("%H:%M:%S", lt)	
	
	if wb[ ] < strftime("%H:%M:%S",lt):
                 print "Wecker ausgelöst!"
(Das Programm soll später 24/7 auf meinem Raspberry laufen, deshalb die endlos-Schleife)

In der Datei "Times.txt" stehen die Zeiten als Beispiel so: 13:45:00.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@SteveGameDE: das Programm ist total kaputt. Zeile 11 liest die gesamte Datei, so dass die Schleife in Zeile 12 nie ausgeführt wird. Zu Zeile 14 hat pixewakb ja schon was geschrieben. Wenn man mit Zeiten arbeiten will, sollte man das datetime-Modul verwenden und nicht intern mit Stringrepresentationen von Zeiten arbeiten. Soll wirklich zweimal pro Sekunde die Datei Times.txt gelesen und deren Inhalt in ein Wörterbuch mit Zahlenindizes gesteckt werden, die immer weiter gezählt werden? Und was soll die Abfrage bedeuten: Irgendeine Zeit soll kleiner als die aktuelle sein? Wenn also 6Uhr als Weckzeit eingetragen ist, soll von 6 bis 24 Uhr immer "Wecker ausgelöst" angezeigt werden?

Das Verwenden eines Wörterbuches hier ist quatsch. Du hast eine Liste mit Zeiten, also ist doch List der sinnvollste Datentyp. Listen werden erzeugt, indem man Elemente anhängt (append):

Code: Alles auswählen

with open('Times.txt') as times:
    alarm_times_unparsed = []
    for line in times:
        alarm_times_unparsed.append(line.strip())
oder kürzer:

Code: Alles auswählen

with open('Times.txt') as times:
    alarm_times_unparsed = [line.strip() for line in times]
als nächstes wollen wir ja keine Strings sondern Zeiten, also müssen wir die Strings in Zeiten umwandeln. Das ist etwas komplizierter, darum schreiben wir erst eine Funktion, die das für einen String macht:

Code: Alles auswählen

def parse_time(time):
    return datetime.datetime.strptime(time, '%H:%M:%S').time()
um diese Funktion dann auf jedes Element der Liste anzuwenden um daraus eine neue Liste zu bauen:

Code: Alles auswählen

alarm_times = []
for alarm in alarm_times_unparsed:
    alarm_times.append(parse_time(alarm))
Natürlich können wir das alles auch in einem Schritt machen:

Code: Alles auswählen

with open('Times.txt') as times:
    alarm_times = [parse_time(line.strip()) for line in times]
Jetzt kommt der Punkt, wo mir nicht klar ist, was Du eigentlich willst, das Vergleichen mit der aktuellen Zeit. Hier mal für alle Zeiten:

Code: Alles auswählen

now = datetime.datetime.now().time()
for alarm_time in alarm_times:
    if alarm_time < now:
        print "Wecker ausgelöst: {0:%H:%M:%S}!".format(alarm_time)
Wie Du siehst, braucht man nirgends eine laufende Nummer, einen Index, weil man Python immer nur sagt: "mach für alle Elemente der Liste das selbe" (per for-Schleife) ist es ja egal, ob es die erste, die zweite oder die x-te Alarmzeit ist.
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@SteveGameDE
Was mir an Deinem Code auffällt:
  1. Vermeide Sternchenimporte! Damit holst Du Dir aus dem jeweiligen Modul alle Namen in den importierenden Namensraum. Das heißt zum einen, Du hast keinen lesbaren Bezug mehr zur Herkunft eines Namens (bei ``time.sleep`` seh' ich sofort, dass ``sleep()`` aus dem ``time`` Modul stammt), zum anderen läufst Du Gefahr, einen bereits bestehenden Namen im importierenden Modul mit einem aus dem importierten Modul zu überschreiben oder anderst herum:

    Code: Alles auswählen

    >>> from time import *
    >>> print sleep
    <built-in function sleep>
    >>> sleep = 'shit happens!'
    >>> print sleep
    shit happens!
    Zudem importierst Du das ``time`` Modul 2 Zeilen darunter nochmals!?
  2. Schreibe Namen klein, statt ``Weckerzahl`` also ``weckerzahl``. Groß geschriebene Namen sind für Klassen vorbehalten.
  3. Verwende aussagekräftige Namen. Was verbirgt sich hinter ``wb``? Wir, die wir Deine Gedanken nicht lesen können, müssen raten. Du, der vielleicht heute noch weiß, was gemeint ist, weißt das in 6 Wochen vielleicht auch schon nicht mehr!?
  4. Was in Deiner Endlosschleife geschieht, funktioniert so doch nicht, oder? Du öffnest das File ``Times.txt`` und liest dessen Inhalt komplett bis zum Ende. Die ``for``-Schleife im Anschluss wird demnach nie durchlaufen, weil Du bereits am Ende der Datei angekommen bist. Zudem würdest Du ``line``, das auf den Inhalt von ``Times.txt`` verweist mit der ``for``-Schleife gleich wieder an einen anderen Inhalt binden. Schwer zu verstehen, darum mal ein Beispiel:

    Code: Alles auswählen

    >>> line = 'any stuff'
    >>> for line in ('another stuff', 'and', 'so', 'on'):
    ...     print line
    ... 
    another stuff
    and
    so
    on
    >>> print line
    on
    Wie Du siehst ist der Zugriff auf 'any stuff' so nicht mehr möglich, weil ``line`` innerhalb der ``for`` Schleife mehrmals an verschiedene Strings gebunden wird.
  5. Angenommen, Deine ``for`` Schleife würde durchlaufen: So wie das aussieht, möchtest Du verschiedene Weckzeiten aus ``Times.txt`` in Dein Dictionary ``wb`` füllen. Warum aber Dictionary mit händisch erstellen Nummernkeys? Wo und wie greifst Du darauf zu? ``if wb [ ] < strftime...`` kann`s ja nicht sein, oder?
Ich würde so vorgehen: Zuerst liest Du die Weckzeiten ein und legst diese bereits im passenden Format, ich würde ``datetime.time`` verwenden, ab. Wenn Du also eine Datei ``times.txt`` mit dem Inhalt

Code: Alles auswählen

14:15
15:30
18:22
hast, dann würde das im einfachsten Fall so aussehen:

Code: Alles auswählen

>>> wake_up_times = []
>>> with open('times.txt') as file_:
...     for time_string in file_:
...         h, m = time_string.split(':')
...         wake_up_times.append(datetime.time(int(h), int(m)))
... 
>>> wake_up_times
[datetime.time(14, 15), datetime.time(15, 30), datetime.time(18, 22)]
Somit hast Du eine Liste mit den gewünschten Weckzeiten. In einer Schleife schaust Du dann immer wieder nach, ob eine dieser Zeiten erreicht ist und löst dann den Wecker aus.

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Antworten