python / python/cpython

`str.translate` caching values causes incorrect result

Aperta
#144,463 10 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

docs pending
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

Bug report

Bug description:

It seems that str.translate is caching values internally and this is causing unintended results.

When the translation table returns an ordinal or a string ordinal string, it caches the values returned by __getitem__ and will not call the function again. However if you are returning a 2-length string this doesn't occur (and in fact calls __getitem__ an additional time for some reason?).

I expect that the __getitem__ be executed for every character since the function documentation does not mention this caching value and more-so the function behaves inconsistently.

This is likely caused by #65317.

class counting_translate_ord(dict[int, int]):
    def __init__(self) -> None:
        super().__init__()
        self.missing_calls = 0

    def __getitem__(self, key: int) -> int:
        self.missing_calls += 1
        return ord(str(self.missing_calls % 10))


table = counting_translate_ord()

print(("----").translate(table))  # 1111
print(table.missing_calls) # 1
print(("!@#$").translate(table))  # 2345
print(table.missing_calls) # 5


class counting_translate_str(dict[int, str]):
    def __init__(self) -> None:
        super().__init__()
        self.missing_calls = 0

    def __getitem__(self, key: int) -> str:
        self.missing_calls += 1
        return str(self.missing_calls % 10)


table = counting_translate_str()

print(("----").translate(table))  # 1111
print(table.missing_calls) # 1
print(("!@#$").translate(table))  # 2345
print(table.missing_calls) # 5


class counting_translate_2str(dict[int, str]):
    def __init__(self) -> None:
        super().__init__()
        self.missing_calls = 0

    def __getitem__(self, key: int) -> str:
        self.missing_calls += 1
        return format(self.missing_calls, "02d")[:2]


table = counting_translate_2str()

print(("----").translate(table))  # 02030405
print(table.missing_calls) # 5
print(("!@#$").translate(table))  # 07080910
print(table.missing_calls) # 10
CPython versions tested on:

3.12

Operating systems tested on:

Linux

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia eseguendo il riproduttore Python fornito sui tre casi di tabelle di traduzione con conteggio e confronta il numero di chiamate a getitem e i risultati. Individua quindi il punto di ingresso di CPython e i test per str.translate; il lavoro è completato quando il comportamento è coerente con il contratto documentato ed è coperto da test di regressione.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
backend
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.