2016-08-04 27 views
0

Ich habe Probleme mit dem Entfernen von Elementen aus einer Liste. Ich suche eine elegantere Lösung. Vorzugsweise eine Lösung in einer For-Schleife oder Filter.Python Objekte aus der Liste entfernen

Das Ziel des Stücks Code: Entfernen Sie alle leeren Einträge und alle Einträge, die mit einem '#' beginnen, aus dem Konfigurations-Handle.

Im Moment ich verwende:

# Read the config file and put every line in a seperate entry in a list 
configHandle = [item.rstrip('\n') for item in open('config.conf')] 

# Strip comment items from the configHandle 
for item in configHandle: 
    if item.startswith('#'): 
     configHandle.remove(item) 

# remove all empty items in handle 
configHandle = filter(lambda a: a != '', configHandle) 
print configHandle 

Dies funktioniert, aber ich denke, es ist ein bisschen eine böse Lösung ist.

Wenn ich versuche:

# Read the config file and put every line in a seperate entry in a list 
configHandle = [item.rstrip('\n') for item in open('config.conf')] 

# Strip comment items and empty items from the configHandle 
for item in configHandle: 
    if item.startswith('#'): 
     configHandle.remove(item) 
    elif len(item) == 0: 
     configHandle.remove(item) 

Dies ist jedoch versagt. Ich kann nicht herausfinden warum.

Kann jemand mich in die richtige Richtung drücken?

Antwort

0

Sie dürfen ein Element, über das Sie iterieren, nicht ändern.

Stattdessen sollten Sie Dinge wie filter oder Listenkompromittierungen verwenden.

configHandle = filter(lambda a: (a != '') and not a.startswith('#'), configHandle) 
1

Weil Sie die Liste ändern, während Sie darüber iterieren. Sie können eine Liste Verständnis Fahrt dieses Problem zu umgehen verwenden:

configHandle = [i for i in configHandle if i and not i.startswith('#')] 

auch zum Öffnen einer Datei Sie besser eine with Anweisung zu verwenden, die Datei am Ende des Blocks automatisch schließen:

with open('config.conf') as infile : 
    configHandle = infile.splitlines() 
    configHandle = [line for line in configHandle if line and not line.startswith('#')] 

1. Da keine Garantie für externe Links gibt es auf von der Garbage-Collector gesammelt werden. Und Sie müssen sie explizit schließen, was durch Aufruf der Methode close() eines Dateiobjekts geschehen kann, oder, wie erwähnt, eine pythonischere Methode verwenden Sie eine with-Anweisung.

+0

Danke für Ihre Antwort! Ich verstehe die erste Lösung (mit einem Verständnis) nicht vollständig. Wie entfernt diese Zeile sonst die leeren Einträge in der Liste? Denn das macht auch den Trick für mich configHandle = [i für i in configHandle wenn len (i)> 0 und nicht i.startswith ('#')] – DCB

+0

@DCB Wenn Sie 'if line' schreiben, prüft python die Gültigkeit von' line', wenn es als True python ausgewertet wird, führen Sie Ihre Bedingung aus, und in diesem Fall wird eine leere Zeichenfolge als False ausgewertet. Lesen Sie hier mehr https://docs.python.org/3.5/library/stdtypes.html#truth-value-testing – Kasramvd

1

Sie keine Gegenstände entfernen, während Sie laufen, es ist ein häufiger Fehler

0

Ihre filter Ausdruck ist gut; nur die zusätzliche Bedingung Sie suchen:

configHandle = filter(lambda a: a != '' and not a.startswith('#'), configHandle) 


Es gibt auch andere Möglichkeiten, wenn Sie nicht filter verwenden wollen, sondern, wie in anderen Antworten erwähnt, es ist ein sehr schlechte Idee zu versuchen, eine Liste zu ändern, während Sie es durchlaufen. Die Antworten auf die this stackoverflow-Frage bieten Alternativen zur Verwendung von filter zum Entfernen aus einer Liste basierend auf einer Bedingung.