2015-05-27 5 views
6

Hier ist ein bisschen ein Programm, das ich, dass ich schreibe eine csv ein Verzeichnis von Dateien erstellen zu kategorisieren:Pythonischer Weg, mehrere for-Schleifen mit verschiedenen Filtern gegen dieselbe Liste zu verarbeiten?

matches = [] 
for root, dirnames, filenames in os.walk(directory): 
    for filename in fnmatch.filter(filenames, '*[A-Z]*'): 
     matches.append([os.path.join(root, filename), "No Capital Letters!"]) 

    test = re.compile(".*\.(py|php)", re.IGNORECASE) 
    for filename in filter(test.search, filenames): 
     matches.append([os.path.join(root, filename), "Invalid File type!"]) 

Grundsätzlich kann der Benutzer einen Ordner gesammelt und das Programm zeigt Problem-Dateien, die von mehreren Typen sein können (nur zwei hier aufgeführt: keine Dateien mit Großbuchstaben, keine PHP-oder Python-Dateien). Es wird wahrscheinlich fünf oder sechs Fälle geben.

Während dies funktioniert, möchte ich umgestalten. Ist es möglich, so etwas wie

for filename in itertools.izip(fnmatch.filter(filenames, '*[A-Z]*'), filter(test.search, filenames), ...): 
    matches.append([os.path.join(root, filename), "Violation") 

zu tun, während die Lage, den Überblick zu behalten, von denen der ursprünglichen entpackten Listen die verursacht „Verletzung?“

Antwort

4

Eine einfachere Lösung wäre wahrscheinlich nur die Dateien zuerst durchlaufen und dann überprüft eins nach dem anderen gelten:

reTest = re.compile(".*\.(py|php)", re.IGNORECASE) 
for root, dirnames, filenames in os.walk(directory): 
    for filename in filenames: 
     error = None 
     if fnmatch.fnmatch(filename, '*[A-Z]*'): 
      error = 'No capital letters!' 
     elif reTest.search(filename): 
      error = 'Invalid file type!' 

     if error: 
      matches.append([os.path.join(root, filename), error]) 

Dies wird nicht nur die Logik machen viel einfacher, da Sie immer nur überprüfen müssen eine einzelne Datei (anstatt jedes Mal herauszufinden, wie Sie Ihre Prüfmethode für eine Sequenz von Dateinamen aufrufen), wird sie auch nur einmal durch die Liste der Dateinamen iteriert.

Darüber hinaus wird es auch vermeiden, mehrere Übereinstimmungen für einen einzelnen Dateinamen zu generieren; es fügt höchstens einen Fehler hinzu (der erste). Wenn Sie das nicht möchten, können Sie stattdessen error eine Liste erstellen und diese an Ihre Schecks anhängen - natürlich möchten Sie die elif zu if dann ändern, um alle Schecks auszuwerten.

-1

Ich empfehle Ihnen, Blick auf these slides.

David Beazley gibt ein Beispiel für die Verwendung von yield zur Verarbeitung von Protokolldateien.

edit: hier sind zwei Beispiele aus dem pdf, ein ohne Generator:

wwwlog = open("access-log") 
total = 0 
for line in wwwlog: 
    bytestr = line.rsplit(None,1)[1] 
    if bytestr != '-': 
    total += int(bytestr) 
print "Total", total 

und mit Generator (Funktion mit Ausbeute für komplexere Beispiele verwenden kann)

wwwlog = open("access-log") 
bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog) 
bytes = (int(x) for x in bytecolumn if x != '-') 
print "Total", sum(bytes) 
+0

mit Beispiel aktualisiert. Vereinbarte Link-Only-Antworten sind nicht so gut. –

Verwandte Themen