Zeichenketten zählen und ausgeben

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
jaycop12
User
Beiträge: 4
Registriert: Montag 8. Juni 2015, 15:02

Hallo,

ich brauche ein Programm, was die in einer textdatei enthaltenen Zeichenketten(worte) zählt und ausgibt. Der Name der Textdatei kann im Quellcode enthalten sein.

Trennzeichen sind kein bestandteil der Kette, ebenfalls die leere Menge.

ich habe leider keine Ahnung von Python.
Bitte daher um hilfe!

Vielen Dank im vorraus!
BlackJack

@jaycop12: In der Python-Dokumentation gibt es ein Tutorial und für absolte Programmieranfänger wird oft Learn Python The Hard Way empfohlen (nicht vom Namen irritieren lassen).
AxXel001
User
Beiträge: 29
Registriert: Sonntag 7. Juni 2015, 22:22

Ohne das getestet zu haben (sieh es mehr als Beispiel zur Orientierung in die richtige Richtung):

Code: Alles auswählen

class Wordcounter(object):
    def __init__(self, path):
        self.path = path

    def countWords(self):
        with open(self.path, "r") as textfile:
            words = textfile.read()
            return len(words.split(" "))

if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
        print "Usage: %s path" % sys.argv[0]
        sys.exit(1)
    path = sys.argv[1]
    wc = Wordcounter(path)
    try:
        print "%s enthält %d Wöerter" % (path, wc.countWords())
    except IOError:
        print "Fehler beim Lesen der Datei %s" % path
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@AxXel001: um zu wissen, von was ein Skript abhängt, sollten alle imports immer am Anfang der Datei stehen. Der Sinn der Klasse erschließt sich mir jetzt nicht sofort. Das wäre besser eine einfache Funktion.
jaycop12
User
Beiträge: 4
Registriert: Montag 8. Juni 2015, 15:02

Vielen Dank schon mal!

Ich kann da mit leider nicht viel anfangen :roll:

gibt es eine möglichkeit, wenn ich die Datei mit:

Code: Alles auswählen

text = open("bla.txt","r")
öffne und dann die Wörter zu splitten und mit len() zu zählen?

Bsp:

Code: Alles auswählen

text = "hallo du da"
print len(text.split()
)

Hier spuckt es mir dann die Zahl 3 aus
aber mit einer Datei bekomm ich das nicht hin, kommt immer eine Fehlermeldung
Sirius3
User
Beiträge: 18265
Registriert: Sonntag 21. Oktober 2012, 17:20

@jaycop12: und was ist die Fehlermeldung. Bitte poste doch komplette Programmteile, die das Problem wiedergeben und den dazugehörigen Traceback.
Benutzeravatar
sparrow
User
Beiträge: 4535
Registriert: Freitag 17. April 2009, 10:28

Und bitte hier nur den Quellcode posten, den du auch wirklich verwendest (copy + paste). Denn dein 2. Codeauszug funktioniert weder mit noch ohne Datei.
jaycop12
User
Beiträge: 4
Registriert: Montag 8. Juni 2015, 15:02

sparrow hat geschrieben:Und bitte hier nur den Quellcode posten, den du auch wirklich verwendest (copy + paste). Denn dein 2. Codeauszug funktioniert weder mit noch ohne Datei.
Hier fehlt eine Klammer, dann gehts


ich habe jetzt folgendes getan:

Code: Alles auswählen

datei = open("test.txt","r")
text = datei.readlines()
print len(text)
in dem Doc steht "hallo du". Allerdings gibt er mir die Zahl "1" aus.

Nun hab ich gedacht kann ich es vllt so lösen:

Code: Alles auswählen

datei = open("test.txt","r")
text = datei.readlines()
zahl = text.split()
print len(zahl)
Hier kommt aber:

Traceback (most recent call last):
File "C:\Users\Home\Desktop\test.py", line 3, in <module>
zahl = text.split()
AttributeError: 'list' object has no attribute 'split'


diese Idee scheint also nicht zu klappen
BlackJack

@jaycop12: Als erstes solltest Du verstehen warum die beiden Ansätze nicht funktionieren, also warum die 1 im ersten Fall ausgegeben wird, also was diese 1 *bedeutet* und warum im zweiten Fall die Ausnahme kommt, und dann musst Du Dir nur noch die Operationen auf den beteiligten Datentypen anschauen, was die machen und was für Ergebnisse (Typ/Wert) die haben und welche möglichen Operationen sich daraus ergeben. Und dann hast Du eigentlich alles was Du brauchst um diese Aufgabe zu lösen.
AxXel001
User
Beiträge: 29
Registriert: Sonntag 7. Juni 2015, 22:22

Sirius3 hat geschrieben:@AxXel001: um zu wissen, von was ein Skript abhängt, sollten alle imports immer am Anfang der Datei stehen.
Der import ist nur notwendig, wenn die Datei als Hauptdatei gestartet wird. Wenn sie importiert wird, ist sys nicht von Bedetung also macht das sehr wohl Sinn. Ein Programmierer, der sich die Klasse anschaut würde sonst auch verwirrt, da er im Code der Klasse nach der Verwendung von sys suchen würde.
Sirius3 hat geschrieben:Der Sinn der Klasse erschließt sich mir jetzt nicht sofort. Das wäre besser eine einfache Funktion.
Tut sich meiner Meinung nach nicht viel, ob ich es nun streng objektorientiert mache oder eine einfache Funktion schreibe. Ich denke aber, dass gerade einem Anfänger dadurch das Verständnis für OOP in Python näher gebracht, sonst programmiert er am Ende mehr in Funktionen als er sollte ;)

Zum Thema:

Denk mal nach, die Funktion readLines() liest alle Zeilen. Diese werden dann offensichtlich in einer Liste gespeichert. Da dein Textdokument nur eine Zeile hat, befindet sich auch nur ein Element in der Liste. Darum ist das Ergebnis 1.
Die richtige Funktion (und auch sonst viele nützliche Informationen) findest du in der Python Documentation bzw. hier:
https://docs.python.org/2/tutorial/inpu ... ting-files
BlackJack

@AxXel001: Importe gehören an den Anfang des Moduls auch wenn sie nicht in jedem Fall verwendet werden. Es ist wichtiger alle Abhängigkeiten einfach erfassen zu können als die geringe Gefahr das jemand verwirrt sein könnte das ein Import nicht in jeder Klasse verwendet wird.

Du hast da nichts streng objektorientiert gemacht (das geht in Python gar nicht weil es immer noch den nicht gerade kleinen imperativen Teil der Sprache gibt) und zum lernen von OOP gehört in Python auch wann man gerade *keine* Klasse schreibt. Gerade Anfänger sollten das lernen. Objektorientiert bedeutet nicht das man alles in Klassen stecken muss, und insbesondere wird durch das sinnfreie verschieben von Funktionen in Klassen nichts ”objektorientierter”. Funktionen sind auch Objekte, wie alles in Python dem man einen Namen geben kann.

Im Allgemeinen ist eine Klasse die nur aus einer `__init__()` und *einer* Methode besteht ein „code smell“ weil es sich meistens um eine unnötig umständlich geschriebene Funktion handelt.
jaycop12
User
Beiträge: 4
Registriert: Montag 8. Juni 2015, 15:02

Schritt für Schritt zum Erfolg!

Code: Alles auswählen

datei = open("test.txt","r")
for line in datei:
    text = line.split()
    print len(text)
    
So weit habe ich es jetzt und versteh die Logik auch. Nun erhalte ich die Anzahl der Zeichenketten pro zeile und brauche nur noch die summe.
Dann kann ich mich de feinheiten widmen
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

jaycop12 hat geschrieben:Dann kann ich mich de feinheiten widmen
Mal zur Inspiration:

Code: Alles auswählen

$ cat test.txt
bla foo blub, arg
bim und bam!

Code: Alles auswählen

>>> with open('test.txt', 'r') as file_:
...     print sum(len(line.split()) for line in file_)
... 
7
  • Dateiobjekte (in meinem Beispiel an den Namen `file_` gebunden) sollten mit dem with statement erstellt werden. Damit wird dafür gesorgt, dass die Datei in jedem Fall auch wieder geschlossen wird.
  • Python liefert viele nützliche Helfer in Form von sogenannten built in functions gleich mit. Eine davon ist sum.
  • Das was im ``sum()``-Aufruf zwischen den Klammern steht, nennt sich list comprehension und kann dazu beitragen, dass Code etwas übersichtlicher wird, da man sich eine explizite ``for`` Schleife spart.
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Das was Du „list comprehension“ nennst ist eigentlich ein Generatorausdruck. :-)
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@BlackJack
Stimmt... :oops: Damit also heute niemand mehr von mir fehlgeleitet in die Nacht gehen muss, hier noch die Korrektur: Genau genommen müsste es eigentlich so...

Code: Alles auswählen

>>> with open('test.txt', 'r') as file_:
...     print sum((len(line.split()) for line in file_))
...
... oder mit list comprehension so...

Code: Alles auswählen

>>> with open('test.txt', 'r') as file_:
...     print sum([len(line.split()) for line in file_])
...
aussehen.

Ist es ein Beispiel für syntaktischen Zucker, dass die Klammern beim Aufruf an eine Funktion, die eine Sequenz erwartet, weggelassen werden dürfen?

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
bwbg
User
Beiträge: 407
Registriert: Mittwoch 23. Januar 2008, 13:35

Die Klammern beim Generatorausdruck dürfen nur weggelassen werden, wenn dieser das einzige Argument der Funktion ist. Ansonsten ist wieder Klammern angesagt. Ich vermute mal, dass es was mit dem parsing zu tun hat. Hinterfragt hatte ich das nie.
"Du bist der Messias! Und ich muss es wissen, denn ich bin schon einigen gefolgt!"
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Klammern weglassen ist bei generator expressions genauso wenig Zucker wie bei Tupeln. Die sind halt grundsätzlich nicht notwendig aber je nach Kontext halt schon weil damit andere (und halt auch der Parser) noch verstehen was du meinst.
bords0
User
Beiträge: 234
Registriert: Mittwoch 4. Juli 2007, 20:40

DasIch hat geschrieben:Klammern weglassen ist bei generator expressions genauso wenig Zucker wie bei Tupeln. Die sind halt grundsätzlich nicht notwendig aber je nach Kontext halt schon weil damit andere (und halt auch der Parser) noch verstehen was du meinst.
Das ist schlicht falsch. Es ist genau umgekehrt.

Im Gegensatz zu Tupeln, die als Funktionsargumente zusätzliche Klammern benötigen, kann man dort bei generator expressions die sonst stets nötigen Klammern weglassen.
https://docs.python.org/3/reference/exp ... xpressions
Benutzeravatar
pillmuncher
User
Beiträge: 1530
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

bords0 hat geschrieben:Im Gegensatz zu Tupeln, die als Funktionsargumente zusätzliche Klammern benötigen, kann man dort bei generator expressions die sonst stets nötigen Klammern weglassen.
Hm... Dann scheint mein Python kaputt zu sein...

Code: Alles auswählen

>>> def foo(a, b):
...     pass
...
>>> foo('test', x for x in range(3))
  File "<stdin>", line 1
SyntaxError: Generator expression must be parenthesized if not sole argument
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Antworten