Seite 1 von 1

Liste aus file - Elemente verändern

Verfasst: Dienstag 8. Juli 2008, 18:27
von zucki
Hi!

Ich mache grade meine ersten Schritte mit Python und versuche etwa Folgendes:

Code: Alles auswählen

http://firefoxmac.furbism.com/rss_feed.php|||
http://www.forbes.com/leadership/governance/index.xml|||
http://www.forbes.com/ebusiness/index.xml|||
]...]
Diese Liste ist lang, steht in einer Datei, die urls heisst. Da will ich die 3 Striche am Ende löschen.

Also bastle ich mir eine Klasse Textfile:

Code: Alles auswählen

lass textfile:
    ntfiles=0
    
    def __init__(self,fname):
        textfile.ntfiles+=1
        self.name=fname
        self.fh = open(fname)
        self.lines=self.fh.readlines()
        self.nlines=len(self.lines)
        self.nwords=0
        self.wordcount()
    
    def wordcount(self):
        "finds the number of words in the file"
        for l in self.lines:
            w=l.split()
            self.nwords+=len(w)
    
    def grep(self, target):
        "prints out all lines containin target"
        for l in self.lines:
            if l.find(target)>=0:
                print l
Dann definiere ich das Textfile und führe die Methoden aufs Objekt aus:

Code: Alles auswählen

a=textfile('urls')
# print "the number of text files open is", textfile.ntfiles
print "here is some information about them (name, lines, words):"
   
for f in [a]:
    print f.name, f.nlines
    # listenlaenge = f.nlines

# so weit ist das alles klar...
# aber:

for i in range(f.nlines-1):
    one_url=(f.lines[i].split())
    clean_url=
    print clean_url
Das Letzte und natürlich Wichtigste: Wie bekomme ich ich die Strings in der Liste aus Strings quasi in eine Liste aus Chars, sodass ich jeweils die letzten 3 Elemente abschneiden kann?
split() braucht immer einen Separator. Ich habe halt keinen...

Das ist für mich nen Lernbeispiel. Ich kann das sicher ohne Python mit awk auf der Shell machen oder in C++ in 2 Minuten über nen Array.
Allerdings will ich ja Python lernen :)

Hat da wer ne Idee hier?

Gruß,
zucki

Verfasst: Dienstag 8. Juli 2008, 18:32
von Karl

Code: Alles auswählen

>>> s = "string|||"
>>> s[:-3]
'string'
Keine Ahnung, warum du da ne Klasse schreibst, das geht in ein paar Zeilen Pythoncode.
Wenn du mit Klassen rumspielen willst, kannst du dir ja auch 'ne geeignetere Aufgabe dafür suchen :)

Verfasst: Dienstag 8. Juli 2008, 18:35
von EyDu
Strings haben eine replace-Methode, damit kannst du das machen.

Aber was bitte soll das:

Code: Alles auswählen

for f in [a]: 
    print f.name, f.nlines 
? Dann kannst du auch gleich

Code: Alles auswählen

print a.name, a.nlines 
schreiben.

Außerdem kannst du direkt über Listen iterieren und musst nicht den Umweg über die Indizes gehen. Falls du letztere doch brauchst, gibt es enumerate.

Die Klasse finde ich noch etwas seltsam, ich gehe aber mal davon aus, dass du dich auch darin einarbeiten willst.

Verfasst: Dienstag 8. Juli 2008, 18:59
von zucki
Danke für die Tipps ;)

Ich hab Programmieren halt an der Uni gelernt. Da macht man leider alles mit Klassen und OOP. Obwohl es sicher auch anders modellierbar ist. Grad um mal nen bissel Pragmatik reinzukriegen mach ich ja Python.
Wobei ich persönlich finde, dass die Klasse soo seltsam gar nicht is *g*.

Code: Alles auswählen

for i in range(a.nlines-1):
    one_url=a.lines[i]
    one_url=one_url[:-4]
    print "add " + "\"" + one_url + "\""


Ist so ne Art best-Practise. Config files schreiben lassen und so. Jetzt nimmt das Skript jede url und formatiert sie syntaktisch um, sodass ein anderes Programm damit auch was anfangen kann.

Ja... erste Schritte :)

Gruß,
zucki

Verfasst: Dienstag 8. Juli 2008, 19:12
von Trundle
Und was ist daran jetzt pragmatischer als direkt über das Dateiobjekt zu iterieren und sich einmal Indexerei zu sparen?

Verfasst: Dienstag 8. Juli 2008, 19:14
von DasIch
Öffne Die Datei, iteriere über jede Zeile und wenn sie den Bedingungen entspricht füg sie einer Liste zu. Wenn du mehr als 15 Zeilen brauchst, hast du imho was falsch gemacht.

Verfasst: Dienstag 8. Juli 2008, 19:21
von audax
Keep it simple, stupid!

Man kann auch objektorientiert Arbeiten ohne Klassen zu erstellen.

Und so ginge es auch:

Code: Alles auswählen

text = """\
http://firefoxmac.furbism.com/rss_feed.php|||
http://www.forbes.com/leadership/governance/index.xml|||
http://www.forbes.com/ebusiness/index.xml||| 
""".split()

def iter_strip(iterable):
    for line in iterable:
        yield line.rstrip('|')

for line in iter_strip(text):
    print line
wobei die Funktion natürlich auch wieder überflüssig ist, aber die hab ich zum Besseren Verständnis gelassen.
Die nimmt ein beliebiges Iterable von String und entfernt dort die '|' am Ende.

Verfasst: Dienstag 8. Juli 2008, 19:39
von BlackJack
@zucki: Du solltest mal das Tutorial aus der Dokumentation durcharbeiten und PEP8, den "style guide" lesen. Das was Du da machst ist in Python jedenfalls nicht unbedingt "best practise".

Dateien die man öffnet, sollte man auch wieder schliessen. Insbesondere wenn man eine (IMHO unnötige) Referenz darauf behält.

Die Anzahl der Zeilen würde ich nicht als Attribut speichern, weil man damit die Information dupliziert, die man auch mit `len()` vom Attribut `lines` bekäme. Wenn man solche Daten redundant hält, besteht immer die Gefahr, dass sie irgendwann mal "auseinanderlaufen". Wenn es so ein Attribut auf Deinen Objekten geben soll, kann man das auch mit einem Property weiter delegieren. Oder man definiert `Textfile.__len__()`.

Pythonischer, allerdings ungetestet:

Code: Alles auswählen

class Textfile(object):
    def __init__(self, filename):
        self.name = filename
        in_file = open(filename, 'r')
        self.lines = list(in_file)
        in_file.close()
    
    def __iter__(self):
        return iter(self.lines)
    
    def __len__(self):
        return len(self.lines)
    
    def count_words(self):
        return sum(len(line.split()) for line in self)
    
    def grep(self, needle):
        for line in self:
            if needle in line:
                print line


def main():
    urls = Textfile('urls')
    print urls.name, len(urls), urls.count_words()
    for url in urls:
        print 'add "%s"' % url[:-4]


if __name__ == '__main__':
    main()