input bei liste

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.
haeuslermartin
User
Beiträge: 66
Registriert: Sonntag 21. April 2013, 10:12

hallo, ich schlag mich schon seit vielen Tagen mit folgendem Problem herum:
(bei den Grundlagen in Büchern bin ich da auch nicht weitergekommen, vielleicht auch nicht, weil ich nicht weiß, wo ich suchen soll...)
Ich möchte einer Liste mit Zahlen eine Reihe von Zahlen hinzufügen.
Mit liste[] und liste.extend kein Problem, aber ein Anwender muß doch wohl die Zahlen über "input" eingeben, ich habe schon alles mir mögliche versucht,
z.B. liste.extend = int(input"zahlen: ")), oder einfach nur input mit anschließender umwandlung in integer und vieles mehr, aber ich habe keine Lösung gefunden..

Dabei ist es sicher einfach, ein User gibt ein paar Zahlen ein, (z.B. Lottozahlen, die der Liste hinzugefügt werden.)(python version 3.3)
vielen Dank für einen Tipp im voraus, Martin.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Mit extend erweiterst du die Liste um Elemente einer weiteren Liste. Wenn du ein einzelnes Element hinzufügen willst, dann verwende append. (siehe auch im Tutorial unter http://docs.python.org/3/tutorial/datas ... e-on-lists)

Aber auch dort solltest du darauf achten wie die korrekte Syntax ist. Mit der von dir vorgeschlagenen Syntax würdest du bei liste.append = element landen. append ist aber eine Methode und muss entsprechend aufgerufen werden. Folglich heißt es liste.append(element).
haeuslermartin
User
Beiträge: 66
Registriert: Sonntag 21. April 2013, 10:12

okay, danke, das eine war ein Tippfehler, ich weiß, liste.extend().. Es soll eine Reihe von Zahlen sein, also extend, aber meine Frage bezog sich
auf die Eingabemöglichkeit eines potentiellen Users, der kann ja nicht Code eintippen, also das Ganze mit "input", das ist es, wohinter ich nicht komme..
wie ich in meiner ersten Anfrage schon geschildert habe, vielleicht könnt Ihr mir da ein wenig weiterhelfen..
Martin
BlackJack

@haeuslermartin: Da kann man entweder eine Schleife schreiben und den Benutzer nach jeder Zahl einzeln Fragen und die Zeichenkette in eine Zahl umwandeln und mit `append()` an die Liste anhängen, die man vor der Schleife als leere Liste angegeben hat. Oder man fragt den Benutzer nach allen Zahlen, die er zum Beispiel durch Leerzeichen getrennt eingeben kann, und verarbeitet diese Zeichenkette dann weiter. Trennen an den Leerzeichen in eine Liste, umwandeln jedes Elements in eine Zahl und anhängen der Zahl an die Liste in der am Ende die Zahlen stehen sollen.
BlackJack

Mal als Code:

Code: Alles auswählen

def main():
    # 
    # Eingabe der Zahlen einzeln:
    # 
    print('Lottozahlen eingeben:')
    lottozahlen = list()
    for i in range(6):
        lottozahlen.append(int(input('  {0}. Zahl: '.format(i + 1))))
    print(lottozahlen)
    # 
    # Als „list comprehension”:
    # 
    print('Lottozahlen eingeben:')
    lottozahlen = [int(input('  {0}. Zahl: '.format(i + 1))) for i in range(6)]
    print(lottozahlen)
    # 
    # Eingabe aller Zahlen in einem `input()`:
    # 
    lottozahlen = list()
    print('Lottozahlen durch Leerzeichen getrennt eingeben:')
    for string in input().split():
        lottozahlen.append(int(string))
    print(lottozahlen)
    # 
    # Und wieder als „list comprehension”:
    # 
    print('Lottozahlen durch Leerzeichen getrennt eingeben:')
    lottozahlen = [int(string) for string in input().split()]
    print(lottozahlen)


if __name__ == '__main__':
    main()
Was hier natürlich fehlt ist die Behandlung von Fehleingaben. Wenn der Benutzer keine Zahlen eingibt, oder wenn er Zahlen ausserhalb von 1 und 49 eingibt, oder nicht jede Zahl nur einmal eingegeben wird.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Nun der User kann natuerlich schon Code eingeben und den kann man auch recht gut auswerten:

Code: Alles auswählen

>>> answer = input()
[1, 2, 3, 23, 42]
>>> answer
'[1, 2, 3, 23, 42]'
>>> import ast
>>> ast.literal_eval(answer)
[1, 2, 3, 23, 42]
>>> numbers = []
>>> numbers.extend(ast.literal_eval(answer))
>>> numbers
[1, 2, 3, 23, 42]
Aber Benutzerfreundlich ist das nicht unbedingt.
BlackJack

@cofi: Eine leere Liste mit `extend()` zu erweitern macht nicht so viel Sinn, da kann man doch gleich da Ergebnis von `literal_eval()` an `numbers` binden.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

@BlackJack: Natuerlich, ich wollte nur nahe am Eingangsbeispiel bleiben ;)
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

cofi hat geschrieben:Aber Benutzerfreundlich ist das nicht unbedingt.
Was hälst du von json?

Code: Alles auswählen

>>> import json
>>> answer = input()
[1, 2, 3]
>>> answer
'[1, 2, 3]'
>>> meine_liste = json.loads(answer)
>>> meine_liste
[1, 2, 3]
>>> meine_liste.append(42)
>>> meine_liste
[1, 2, 3, 42]
>>> 
Xe
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Willst du jetzt sagen, dass JSON benutzerfreundlicher sein soll?
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

cofi hat geschrieben:Willst du jetzt sagen, dass JSON benutzerfreundlicher sein soll?
Wollte ich nicht, aber wenn ich mir anschaue, wie komplex/vielschichtig ast ist und wie schlicht json, dann würde ich das sogar sagen. Das sage ich nach einem Vergleich von dir(ast) (1000 Sachen) mit dir(json) (load und dump) im Hinblick auf das gegebene Problem.

Xe
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Hier zusätzlich noch eine anfängergerechte Variante, in der pro Zeile möglichst wenig geschieht:

Code: Alles auswählen

def main():
    print('Lottozahlen eingeben:')
    lottozahlen = []
    for i in range(1,7):
        eingabe_prompt = ' %s. Zahl: ' % (i,)
        eingabe = input(eingabe_prompt)
        lottozahl = int(eingabe)
        lottozahlen.append(lottozahl)
    lottozahlen.sort()
    print(lottozahlen)

if __name__ == '__main__':
    main()
BlackJack

@xeike: Von diesem Unterschied sieht doch aber Benutzer der etwas eingibt überhaupt nichts. Für den kann es doch egal sein wie Umfangreich der Verarbeitungscode ist. Was er sieht sind JSON oder Python-Code der nur aus literalen Werten bestehen darf. Da hat Python ein wenig mehr zu bieten, und damit auch zu lernen, aber im Fall von der Zahleneingabe als Liste ist das Python-Literal doch identisch mit JSON. Also gar kein Unterschied.

Das `ast`-Modul ist natürlich umfangreicher, weil es die gesamte Programmiersprache verarbeiten können muss. Das trifft aber nicht auf `literal_eval()` zu. Das ist ja nur ein kleiner Teil der Funktionalität, die das `ast`-Modul bietet.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

@xeike: Der Benutzer ist hier derjenige, der die Daten eingibt, nicht der Programmierer. Und selbst der sieht von `ast` eben nur `literal_eval`.
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

@cofi: Endbenutzerfreundlichkeit bei einem Testprogramm? Na, OK, von mir aus.
haeuslermartin
User
Beiträge: 66
Registriert: Sonntag 21. April 2013, 10:12

liebe Python-Gemeinde, lieber Blackjack, vielen Dank !!
ich habe mich für die Variante "Eingabe aller Zahlen entschieden, das ist sehr einfach und funktioniert wunderbar:
zum Beispiel:

lottozahlen = list([2,5,33,22,3]) #die bereits vorhandenen Zahlen
print('Lottozahlen durch Leerzeichen getrennt eingeben:')
for string in input().split():
lottozahlen.append(int(string))
print(lottozahlen)

#die Ausgabe in der shell:

Lottozahlen durch Leerzeichen getrennt eingeben:
2 33 32 43 45 1 7
[2, 5, 33, 22, 3, 2, 33, 32, 43, 45, 1, 7]

Die Behandlung von Fehleingaben fürchte ich, übersteigt meinen momentanen python-Horizont, ebenso die Arbeit mit importierten Modulen.. jetzt habe ich erstmal genug Material zum Lernen, und zu gegebener Zeit wäre ich froh, Euch wieder fragen zu dürfen.
Martin.
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

@BlackJack: Nitpick: Es gibt in Python keine Literale für Listen. list displays sind keine Literale (auch wenn literal_eval sie auswertet).
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

Hi!
haeuslermartin hat geschrieben:Die Behandlung von Fehleingaben fürchte ich, übersteigt meinen momentanen python-Horizont,
Wenn du mit einer Menge (set) arbeitest statt einer Liste, dann hättest du schon mal keine doppelten Einträge.

Bei den Lottozahlen kann u. a. folgendes passieren (in Klammern Möglichkeiten, das zu testen):

* zu viele oder zu wenige Zahlen ( len(Liste oder Menge) )
* Benutzer geben keine Zahlen sondern irgend etwas anderes ein (string.isdecimal())
* leere Eingabe, also einfach RETURN gedrückt ( len(eingabe) )

Damit hättest du dann schon eine Reihe von Fehlern abgefangen.

Wenn du die Lottozahlen sortiert ausgeben möchtest, dann kannst du lottozahlen.sort() probieren.

Xe
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

haeuslermartin hat geschrieben:Die Behandlung von Fehleingaben fürchte ich, übersteigt meinen momentanen python-Horizont
In diesem Fall nimm doch die anfängerfreundliche Variante (dafür ist sie da). In der Zeile

Code: Alles auswählen

lottozahl = int(eingabe)
kannst Du Dich dann der Fehlerbehandlung widmen, denn dies ist die Stelle, wo bei Falscheingaben die Konvertierung schief geht, oder auch auf Zahlen ausserhalb eines gültigen Intervalls getestet werden kann. Weiter könntest Du an dieser Stelle prüfen, ob die Zahl bereits eingegeben wurde (das lässt sich mit Sets zwar umgehen, aber dabei lernt man nichts).
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

kbr hat geschrieben: (das lässt sich mit Sets zwar umgehen, aber dabei lernt man nichts).
Hm... ich sehe hier der *einzelnen* Eingabe von Zahlen keinen besonderen Vorteil eines sets. Ich kann genauso gut auf der Liste prüfen, ob die Zahl schon darin enthalten ist (``value in values``), bevor ich sie hinzufüge. Abgesehen von der schnelleren Laufzeit für das Prüfen bei sets, müsste man da ja analog vorgehen. Denn einfach einfügen und *danach* die Länge prüfen halte ich für umständlich. Dass ist eher dann sinnvoll, wenn der Benutzer alle Zahlen auf einmal eingibt und diese dann ausgewertet werden. Insofern ist set sicherlich nicht verkehrt, aber auch kein Muss in diesem Kontext.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten