Ta bort specifika tecken från en sträng i Python

Jag försöker ta bort specifika tecken från en sträng med hjälp av Python. Detta är den kod jag använder just nu. Tyvärr verkar den inte göra något med strängen.

for char in line:
    if char in " ?.!/;:":
        line.replace(char,'')

Hur gör jag detta på rätt sätt?

Lösning

Strängar i Python är immutabla (kan inte ändras). På grund av detta är effekten av line.replace(...) bara att skapa en ny sträng, snarare än att ändra den gamla. Du måste återbinda (tilldela) den till line för att få den variabeln att ta emot det nya värdet, med dessa tecken borttagna.

Dessutom kommer det sätt du gör det på att vara ganska långsamt, relativt sett. Det är också troligt att det blir lite förvirrande för erfarna pythonatorer, som kommer att se en struktur med dubbla höljen och för ett ögonblick tro att det är något mer komplicerat som pågår.

Från och med Python 2.6 och nyare Python 2.x-versioner * kan du istället använda str.translate, (men läs vidare om skillnaderna i Python 3):

line = line.translate(None, '!@#$')

eller ersättning av reguljära uttryck med re.sub

import re
line = re.sub('[!@#$]', '', line)

Tecknen inom parentes utgör en teckenklass. Alla tecken i line som ingår i den klassen ersätts med den andra parametern till sub: en tom sträng.

I Python 3 är strängar Unicode. Du måste översätta lite annorlunda. kevpie nämner detta i en kommentar till ett av svaren, och det noteras i dokumentationen för str.translate.

När du anropar translate-metoden för en Unicode-sträng kan du inte lämna över den andra parametern som vi använde ovan. Du kan inte heller lämna över None som första parameter, eller ens en översättningstabell från string.maketrans. Istället lämnar du över en ordbok som enda parameter. Denna ordbok mappar ordinalvärdena av tecken (dvs. resultatet av att kalla ord på dem) till ordinalvärdena av de tecken som ska ersätta dem, eller - vilket är användbart för oss - None för att indikera att de ska raderas.

Så för att göra ovanstående dans med en Unicode-sträng skulle du kalla något i stil med

translation_table = dict.fromkeys(map(ord, '!@#$'), None)
unicode_line = unicode_line.translate(translation_table)

Här används dict.fromkeys och map för att kortfattat generera en ordbok som innehåller

{ord('!'): None, ord('@'): None, ...}

Ännu enklare, som ett annat svar uttrycker det, är att skapa ordboken på plats:

unicode_line = unicode_line.translate({ord(c): None for c in '!@#$'})

* För att vara kompatibel med tidigare Pythons kan du skapa en "null" översättningstabell som du kan skicka i stället för None:

import string
line = line.translate(string.maketrans('', ''), '!@#$')

Här används string.maketrans för att skapa en översättningstabell, som bara är en sträng som innehåller tecken med ordningsvärdena 0 till 255.

Kommentarer (7)
line = line.translate(None, " ?.!/;:")
Kommentarer (2)

Strängar är oföränderliga i Python. Metoden replace returnerar en ny sträng efter ersättningen. Försök:

for char in line:
    if char in " ?.!/;:":
        line = line.replace(char,'')
Kommentarer (3)