Problem z usuwaniem elementu listy

0

Witam,
Czy może mi ktoś wytłumaczyć co tu się dzieje, bo ja już nie wiem.

Otóż, jest sobie string sttr oraz jest lista out zawierająca pierwsze litery grup znaków D (digits), P (punctuation), L (lowercase), U (uppercase).
Pętla for ma zadanie, aby z listy usunąć oznaczenia występujących znaków.
W moim stringu występują wszystkie cztery grupy. Jest literka mała, jest literka duża, jest cyferka i znaki specjalne.

from string import ascii_lowercase, ascii_uppercase, digits, punctuation

sttr = 'Lo$a2@'

out = ['D', 'L', 'P', 'U']

try:
    for i in sttr:
        if i in [x for x in ascii_uppercase]:
            out.remove('U')
        elif i in [x for x in ascii_lowercase]:
            out.remove('L')
        elif i in [x for x in digits]:
            out.remove('D')
        elif i in [x for x in punctuation]:
            out.remove('P')
except ValueError:
    pass

print(out)

I po tym princie z niewiadomych mi powodów otrzymuję to:

['D']

I nie mam zielonego pojęcia dlaczego tak się dzieje. Wygląda tak, jakby out.remove('D') nie działało.

1

Wywal try/except to się dowiesz. Kod próbuje usunąć usunięty już element stąd w tym momencie iteracja się wywala (passuje) i reszta skryptu idzie dalej. Jak dasz try/except bezpośrednio w pętli to masz taki fajny kewyord continue, który będzie kontynuował iteracje.

Wywalanie się wynika z tego, że string zawiera dwie małe liter o i a. Przy o triggeruje się elif z out.remove('L') tak samo jak przy a. Z tą różnicą, że przy tej drugiej tego L już nie ma bo został usunięty, więc wywala błąd,

sttr = 'Lo$a2@'

out = ['D', 'L', 'P', 'U']

for i in sttr:
    try:
        print(i)
        if i in ascii_uppercase:
            out.remove('U')
        elif i in ascii_lowercase:
            out.remove('L')
        elif i in digits:
            out.remove('D')
        elif i in punctuation:
            out.remove('P')
    except ValueError:
        continue
print(out)
3

Zamiast iterować po znakach możesz po prostu robić operacje na setach:

from string import ascii_lowercase, ascii_uppercase, digits, punctuation

sttr = 'Lo$a2@'
out = ['D', 'L', 'P', 'U']

str_set = set(sttr)
if str_set & set(digits):
    out.remove('D')
if str_set & set(ascii_lowercase):
    out.remove('L')
if str_set & set(punctuation):
    out.remove('P')
if str_set & set(ascii_uppercase):
    out.remove('U')

print(out)

Jak usuwasz po jednym na raz to nie musisz się martwić, że kiedyś poleci jakiś wyjątek z racji tego, że danej litery w out już nie ma.

1 użytkowników online, w tym zalogowanych: 0, gości: 1