python2to3

Du hast eine Idee für ein Projekt?
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

BlackJack hat geschrieben:@Nobuddy: Ich habe `b` an etwas anderes gebunden als Du. Mit 'Hallo' gibt es keine Probleme denn das besteht nur aus Zeichen bei denen die `repr()`-Darstellung den ursprünglichen Zeichen entspricht.
Sehe es gerade, der kleine Unterschied (oö) ...
In meinem Pythonterminal bekomme ich die gleiche Ausgabe wie Du, ist wirklich ein Problem.
Ich habe es mit meinem Code versucht. Habe 'Flöte' für die erste Spalte und 'Gänse' für die zweite Spalte, sowie 'flöte' für die dritte Spalte genommen. Anschließend habe ich nur nach ä und ö gesucht und bekam bei beiden das richtige Ergebnis. Allerdings bei der Suche nach ',' bekomme ich auch Ergebnisse ausgespuckt, die kein Komma beinhalten.
Bin ich jetzt auf der falschen Spur, so daß ich Dich missverstehe, oder funktioniert der Code den ich dafür angedacht habe doch richtig?
BlackJack hat geschrieben:Meine Frage zum Funktionsablauf beschränkte sich eigentlich nur auf die `search_entry()`-Funktion, und da auf das ``if``/``elif`` mit dem die Datensätze geprüft werden. Was hast Du Dir bei den beiden Bedingungen gedacht, was erfasst die erste und was die zweite, und was beide?
Ich hatte das schon weiter oben schon mal erklärt.
Zu der Funktion 'search_entry'.
Die Liste habe ich so aufgebaut, daß in der ersten Spalte Begriffe zu Python2, in der zweiten Spalte Begriffe zu Python3 und in der dritten Spalte ein Info dazu steht.
Ich suche zuerst einmal in der ersten Spalte mit dem Python2-Begriff also 'item[0]'.
Beispiel: 'flöte'
Finde ich in 'item[0]' nichts, so durchsuche ich die komplette Zeile des Datensatzes und finde hier in diesem Beispiel dann 'flöte' in der dritten Spalte.
Es ist also möglich eine 1:1 Suche in der ersten Spalte (Beispiel: Flöte), wie auch eine Suche über einen Teilbegriff (Beispiel: öte) im Datensatz zu suchen.

Bitte sag mir Bescheid, wenn Du etwas anderes meinst, damit ich Dir die richtige Antwort geben kann.

PS: Bin dabei Deinen Link durch zugehen.
BlackJack

@Nobuddy: Das hast Du ja alles schon mal gesagt zu der Suche. Jetzt nenne doch mal Werte für `entry` und `item` bei denen der erste Test zutrifft und der zweite *nicht* zutreffen würde.

Und ist Dir klar warum das ',' in jedem Datensatz gefunden wird? Weisst Du was eine Liste ist? Und was eine Zeichenkette ist? Und das eine Zeichenkettendarstellung einer Liste nicht das selbe ist wie die Liste selbst?
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

BlackJack hat geschrieben:@Nobuddy: Das hast Du ja alles schon mal gesagt zu der Suche. Jetzt nenne doch mal Werte für `entry` und `item` bei denen der erste Test zutrifft und der zweite *nicht* zutreffen würde.
Ok, jetzt habe ich verstanden, was Du mir damit sagen möchtest.
Das Ganze ist 'doppelgemopplet', eine Zeile zur Suche würde reichen und noch kürzer gestalten.
Aus:

Code: Alles auswählen

                for item in reader:
                    if item[0] == entry:
                        line = item[0], item[1], item[2]
                        data.append(line)
                    elif entry in str(item):
                        line = item[0], item[1], item[2]
                        data.append(line)
wird:

Code: Alles auswählen

                for item in reader:
                    if entry in str(item):
                        data.append(item[:])
Das wolltest Du mir doch damit mitteilen, oder?
BlackJack hat geschrieben:Und ist Dir klar warum das ',' in jedem Datensatz gefunden wird? Weisst Du was eine Liste ist? Und was eine Zeichenkette ist? Und das eine Zeichenkettendarstellung einer Liste nicht das selbe ist wie die Liste selbst?
Ich denke ja. Eine Liste besteht aus Strings (Zeichenketten). Eine Zeichenkettendarstellung enthält außer den Strings zusätzliche Zeichen, wie Begrenzungszeichen für Zeichenketten (,) sowie den Anfang und Ende der Liste (...). Eine Liste selbst enthält nur Strings (Zeichenketten).
Da ich eine Anzahl von Zeichenketten in einen String umwandle, werden diese durch ein Komma (,) getrennt.
Suche ich jetzt in diesem String nach einem Teilstring, so wird das Komma auch als Teil der Zeichenkette betrachtet.

Beim erklären, tue ich mich als schwer, hoffe aber daß es so richtig ist?
BlackJack

@Nobuddy: Genau auf die Vereinfachung wollte ich hinaus.

Warum erstellst Du eine Kopie von `item`? Das ist übrigens ein irreführender Name — für Containerobjekte wäre die Mehrzahl passender denn der Name steht nicht für ein Objekt sondern für eine Sammlung von mehreren Objekten.

Die Zeichenkettenerklärung stimmt auch.

Man sollte keine Objekte in Zeichenketten umwandeln und darauf Operationen durchführen, wenn man stattdessen die Operationen direkt mit den Operationen ausdrücken kann. Es sind ja nicht nur die zusätzlichen Kommas, Leerzeichen, eckigen Klammern und Anführungszeichen, sondern auch die ursprünglichen Zeichenketten werden verändert wenn man sie per `repr()` in eine Zeichenkette „umwandelt”. Denn das macht die Zeichenkettendarstellung von Listen: `repr()` für jedes Element aufrufen und daraus die Zeichenkette zusammen bauen. Deswegen wurde Hällö in meinem Beispiel nicht gefunden.

Die ganze ``for``-Schleife könnte man recht kompakt als „list comprehension” (LC) formulieren:

Code: Alles auswählen

    result = [row for row in reader if any(entry in x for x in row)]
Vom Entwurf wäre es besser wenn man die Geschäftslogik von der Benutzerinteraktion trennen würde. Dann kann man die Funktionen einfacher automatisiert testen und später vielleicht auch eine kleine GUI schreiben ohne das ganze Programm neu schreiben zu müssen.
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

@BlackJack, Du und die Anderen, habt mich ja schon mehrmals versucht darauf aufmerksam zu machen, aber da habe ich "vor lauter Wald, die Bäume nicht gesehen". Danke dafür und Eure Geduld. :wink:

Das mit den Namen, ist wirklich ein Problem bei mir. Einerseits hatte ich schon vor deutsche Namen zu verwenden, andererseits ist ja hier Englisch, die gewünschte Sprache. Da muß ich wirklich noch eine klare Linie rein bekommen.

Wow, das mit der „list comprehension” ist wirklich beeindruckend, wie zielgerichtet Du das hier mir dargelegt hast.
Wie sollte es auch anderst sein, funktioniert 100-prozentig. :)
Bei der „list comprehension” programmierst Du von innen nach außen, ist das richtig?
'for row in reader', sowie 'entry in x for x in row' ist mir klar.
Wo ich noch überlege, ist das 'row' ganz links vor der eckigen Klammer und 'if any('.
Kann es sein, daß 'if any(' sich auf 'row' bei 'for row in reader' bezieht und das ganz linke 'row' die Ausgabe erhält?

Ich habe das mal so eingebaut:

Code: Alles auswählen

def search_entry(menupoint):
    while True:
        entry = input('\nSuchbegriff: ')
        if entry:
            print("\nListe wird nach Suchbegriff durchsucht!")
            with open(datapool, 'r') as infile:
                reader = csv.reader(infile, delimiter="\t", quotechar="^")
                result = [row for row in reader if any(entry in x for x in row)]
            if not result:
                print('\nEs liegen keine Ergebnisse zu dem Suchbegriff %s vor\n' % entry)
                break
            else:
                selection(menupoint, result)
                break
BlackJack hat geschrieben:Vom Entwurf wäre es besser wenn man die Geschäftslogik von der Benutzerinteraktion trennen würde. Dann kann man die Funktionen einfacher automatisiert testen und später vielleicht auch eine kleine GUI schreiben ohne das ganze Programm neu schreiben zu müssen.
Bin mir jetzt nicht sicher, ob das richtig verstehe.
Meinst Du, daß für jeden Menüpunkt man ein eigenes Modul erstellen soll?
Also search_entry.py, add_entry.py ... usw.
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,
habe mich mit „list comprehension” beschäftigt und mir ist jetzt einiges klarer.
Ich habe dies auch versucht im Code umzusetzen, was nicht immer funktionierte und so noch manches umständlich ist, was mich selbst stört.

Poste hier mal den aktuellen Code: https://gist.github.com/3361291

Die Funktion 'selection' ist ziemlich aufgebläht und dadurch wahrscheinlich auch wieder umständlich gemacht. Mit „list comprehension” würde sich da vielleicht noch einiges vereinfachen, was ich aber nicht geschafft habe.
Der erste Teil der Funktion, beschäftigt sich damit, daß die Überschriftzeile und die Datenausgabe die gleiche vertikale Ausrichtung haben sollen, dies sorgt bei der Ausgabe für eine bessere Übersicht.

Was mich auch beschäftigt, ist wie ich es hin bekomme den Code flexibel zu halten, daß wenn eine Datendatei mehr Spalten als wie hier in diesem Beispiel hat, der Code nicht erneut angefasst werden muß.
Dabei handelt es sich um diese Zeilen:

Code: Alles auswählen

        print('\n-----\n{}:\t{}:{}{}:{}{}:'.format(splitinfos[0], splitinfos[1], ' ' * (4 + (resultcount[0] - splitcount[0])), splitinfos[2], ' ' * (4 + (resultcount[1] - splitcount[1])), splitinfos[3]))

        dataline = dict()
        for index, row in enumerate(result):
            print('{}:\t{}{}{}{}{}\n'.format(int(index + 1), row[0], ' ' * (5 + (resultcount[0] - len(row[0]))), row[1], ' ' * (5 + (resultcount[1] - len(row[1]))), row[2]))
            dataline[int(index + 1)] = [row]
        print('-----')
Vielleicht könnt Ihr mir die Richtung zeigen, wie man den Code noch mehr vereinfachen kann?
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Hallo zusammen,
es gab Änderungen in meinem Code, daher möchte ich Euch den aktuellen Code hier vorstellen: https://gist.github.com/3436664

Bitte seit nicht enttäuscht, denn es gibt immer noch einige Baustellen, die ich aber hoffe mit Eurer Hilfe zu beseitigen.
Das soll nicht heißen, daß Ihr für mich den Code schreiben sollt :lol: , sondern mir die einzelnen Baustellen nach und nach aufzeigt und ein paar verständliche Stichpunkte dazu, die es mir ermöglichen, das dann umzusetzen ...., da ich manchmal den Wald vor lauter Bäumen nicht sehe. :wink:
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Nobuddy hat geschrieben:Vielleicht könnt Ihr mir die Richtung zeigen, wie man den Code noch mehr vereinfachen kann?
Ich hab keine Ahnung was du da genau machst. Aber sicherlich ist es schon mal hilfreich, wenn du den code anders formatierst. Ein Vorschlag:

Code: Alles auswählen

print('\n-----\n')
print('{}:\t{}:{}{}:{}{}:'.format(
    splitinfos[0],
    splitinfos[1],
    ' ' * (4 + (resultcount[0] - splitcount[0])),
    splitinfos[2],
    ' ' * (4 + (resultcount[1] - splitcount[1])), 
    splitinfos[3]
))

dataline = dict()
for index, row in enumerate(result):
    print('{}:\t{}{}{}{}{}\n'.format(
        int(index + 1),
        row[0],
        ' ' * (5 + (resultcount[0] - len(row[0]))),
        row[1],
        ' ' * (5 + (resultcount[1] - len(row[1]))),
        row[2]
    ))
    dataline[int(index + 1)] = [row]
print('-----') 
Evtl. macht es Sinn teilweise mit .join zu arbeiten?

EDIT: btw. ich hab den thread hier nicht durchgelesen. Vielleicht macht es mehr Sinn 2to3 zu nehmen, den code zu convertieren und dann zu vergleichen...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Hallo jens,
Danke für Deine Rückmeldung und Deinen Vorschlag, sieht übersichtlicher aus!

Was ich hier mache, will ich Dir kurz erklären.
Als erstes kommt es nicht darauf an, daß ich wie hier im Beispiel, Änderungen von Python-2-Code zu Python-3-Code als Aufgabe verwende. Ich möchte soweit es geht den Code unabhängig und flexibel halten, so daß man dies auch für eine Adress- oder Telefonliste verwenden kann. Die zwei einzigen Dinge, was man im Code ändern muß, ist 'splitinfos' und den Namen der Datendatei, die sich im gleichen Verzeichnis befinden sollte. Je nachdem wieviel Spalten auf der Konsole ausgegeben werden sollen, muß auch der Bereich (Dein VBorschlag) angepasst werden.
Das anfängliche Grundegerüst, habe ich von Hyperion Menü-Beispiel.
Da ich noch so gut wie keine Erfahrung mit GUIś habe, verwende ich alleine die Konsole dazu.
Der Bereich (Dein Vorschlag) ist für die Ergebnisausgabe zuständig.
Der erste Teil davon gibt die Überschrift der Spalten aus, der zweite Teil das Ergebnis selbst.
Zuvor habe ich jeweils die maximale Zeichenbreite pro Spalte der Ergebnisausgabe ermittelt, die ich dann hier verrechne, damit die jeweilige Spaltenüberschrift und die Spaltenausgabe vertikal auf einer Linie ist.

Bestimmt lässt sich das evtl. noch einfacher gestalten, momentan fehlt mir aber noch das Wissen dazu.
Ideal wäre, wenn es möglich wäre den Code dieses Bereiches so zu gestalten, daß er individuell auf die Anzahl der Spalten agieren würde. Wie man das hin bekommen könnte, habe ich leider keine Ahnung.
Wenn noch etwas unklar ist, bitte nochmals nachhaken!

Das mit join, ist mir jetzt noch nicht ganz klar, in was für einen Zusammenhang Du das meinst.

PS:
Ich habe schon mal eine größere Datei getestet, mit ca. 90.000 Datensätze und 6 Spalten.
Hat prima funktioniert und selbst bei dieser Datenmenge, noch superschnell dazu.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Überlege doch mal, ob es nicht besser ist, statt einen index besser Namen zu nehmen. Also statt list/tuple ein dict.

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Mit dem Index, erhalte ich eine fortlaufende, zugeordnete Nummer, mit der ich dann eine Auswahl treffen kann.

Beispiel: i
Ich möchte ein paar Datensätze bearbeiten, erhalte bei der Suche 20 Ergebnisse.
Davon möchte ich aber nur genau 3 bearbeiten und zwar Nummer 3, 12 und 17.
Ich gebe bei 'def selection(menupoint, result):' die Nummern ein und erhalte dann genau diese zur Bearbeitung.
Namen wären da wirklich ungeschickter.

Code: Alles auswählen

Suchbegriff: tk

Liste wird nach Suchbegriff durchsucht!

Die Suche ergab folgende Ergebnisse:

-----

Nummer: Python2:               Python3:                     Info:
1:      Tkinter                tkinter                      Namensänderung von Modul Tkinter, neuer Modulnamen ist tkinter. Statt 'from Tkinter import tkinter' gilt nun 'import tkinter'

2:      tkFont                 tkinter.font                 Namensänderung von Modul tkFont, neuer Modulnamen ist tkinter.font

3:      tkMessageBox           tkinter.messagebox           Namensänderung von Modul tkMessageBox, neuer Modulnamen ist tkinter.messagebox

4:      tkSimpleDialog         tkinter.simpledialog         Namensänderung von Modul tkSimpleDialog, neuer Modulnamen ist tkinter.simpledialog

-----
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Das meinte ich nicht.

Du hast ja das:

Code: Alles auswählen

Nummer: Python2:               Python3:                     Info:
Du packst die Überschriften in eine Liste oder Tuple und nutzt einen index zum adressieren davon. Also z.B. splitinfos[1] ist dann Python2...
Bei den eigentlichen Spalten Werte machst du es genau so.

Statt dessen könntest du besser ein dict nehmen. Kann kann man über den "key" die Werte erhalten.

Also ich meine statt:

Code: Alles auswählen

'{}, {}, {}'.format('a', 'b', 'c')
besser:

Code: Alles auswählen

'Coordinates: {latitude}, {longitude}'.format(latitude='37.24N', longitude='-115.81W')
Schau dir mal die Beispiele hier an: http://docs.python.org/library/string.h ... t-examples

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Puhh, anfänglich kann ich Dir noch folgen, doch was dann unter 'besser' von Dir vorgeschlagen wird, muß ich passen.
Ich habe Deinen Link dazu trotz 'Englisch-Handicap' angeschaut und habe auch versucht mehr über 'latitude' und 'longitude' zu Googeln, finde da aber keine Basis an der ich anknüpfen könnte, sorry.
Das Einzige, was ich bekomme, ist etwas über 'Längengrad-Koordinaten' .... :K
BlackJack

@Nobuddy: Für das Beispiel ist das doch vollkommen egal was die Namen bedeuten. Es geht darum wie man die `format()`-Methode benutzen kann.
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Ok, hehe ... habe mich von dem blenden lassen, verstehe jetzt das Ausgabeformat. :wink:
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

So etwas in der Art, wenn ich es richtig verstanden habe:

Code: Alles auswählen

print('Nr.: {}, py2: {}, {}py3: {}, {}info: {}'.format(
    int(index + 1),
    row[0],
    ' ' * (4 + (resultcount[0] - len(row[0]))),
    row[1],
    ' ' * (4 + (resultcount[1] - len(row[1]))),
    row[2]
))
Die Ausgabe:

Code: Alles auswählen

Nr.: 1, py2: Tkinter,            py3: tkinter,                  info: Namensänderung von Modul Tkinter, neuer Modulnamen ist tkinter. Statt 'from Tkinter import tkinter' gilt nun 'import tkinter'
Nr.: 2, py2: tkFont,             py3: tkinter.font,             info: Namensänderung von Modul tkFont, neuer Modulnamen ist tkinter.font
Nr.: 3, py2: tkMessageBox,       py3: tkinter.messagebox,       info: Namensänderung von Modul tkMessageBox, neuer Modulnamen ist tkinter.messagebox
Nr.: 4, py2: tkSimpleDialog,     py3: tkinter.simpledialog,     info: Namensänderung von Modul tkSimpleDialog, neuer Modulnamen ist tkinter.simpledialog
Sagt mir persönlich aber nicht so zu.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Die beiden Formatstrings sehen fuer dich tatsaechlich aehnlich aus?
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Hmm, wenn ich so gefragt werde, liege ich bestimmt daneben. :K
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Code: Alles auswählen

>>> "{} {}".format("funny", "cats")
'funny cats'
>>> "{spam} {eggs}".format(spam="funny", eggs="cats")
'funny cats'
Der Unterschied ist aber auch wirklich subtil :lol:
Das Leben ist wie ein Tennisball.
Nobuddy
User
Beiträge: 1015
Registriert: Montag 30. Januar 2012, 16:38

Ich denke, Ihr habt mich da ein wenig missverstanden.

Das wie:

Code: Alles auswählen

>>> "{} {}".format("funny", "cats")
'funny cats'
>>> "{spam} {eggs}".format(spam="funny", eggs="cats")
'funny cats'
ist hier nicht das Relevante.

Ich hätte gerne mehr Flexibilität im Code, da ja eine spätere Anpassung im Code nicht sein sollte, wenn z.B. statt dem 3-spaltigen 'pythoninfo.txt' eine 5- oder 8-spaltige Datendatei genutzt werden sollte.
Wenn das nicht gehen würde, müßte man dann hier den Code von:

Code: Alles auswählen

            print('{}:\t{}{}{}{}{}\n'.format(
                int(index + 1),
                row[0],
                ' ' * (9 + (resultcount[0] - len(row[0]))),
                row[1],
                ' ' * (9 + (resultcount[1] - len(row[1]))),
                row[2]
))
auf

Code: Alles auswählen

            print('{}:\t{}{}{}{}{}{}{}{}{}\n'.format(
                int(index + 1),
                row[0],
                ' ' * (9 + (resultcount[0] - len(row[0]))),
                row[1],
                ' ' * (9 + (resultcount[1] - len(row[1]))),
                row[2],
                ' ' * (9 + (resultcount[2] - len(row[2]))),
                row[3],
                ' ' * (9 + (resultcount[3] - len(row[3]))),
                row[4]
            ))
ändern.

Eine Code, der sich der Spaltenzahl automatisch anpasst und die Ausgabe so steuert, daß die jeweiligen Spalten, vertikal genau untereinander sind.
Antworten