Cómo iterar correctamente con re.sub () en Python

Quiero hacer un script en Python que cree notas al pie. La idea es buscar todas las cadenas de caracteres del tipo "Some body text.{^}{Some footnote text.}" Y reemplazarlos con "Some body text.^#" , Donde "^#" es el número correcto de la nota al pie. (Una parte diferente de mi script trata de imprimir realmente las notas al pie en la parte inferior del archivo). El código actual que estoy usando para esto es:

 pattern = r"\{\^\}\{(.*?)\}" i = 0 def create_footnote_numbers(match): global i i += 1 return ""+str(i)+"" new_body_text = re.sub(pattern, create_footnote_numbers, text) 

Esto funciona bien, pero parece extraño tener que declarar una variable ( i ) fuera de la función create_footnote_numbers y luego tener que llamarla dentro de esa función. Pensé que habría algo dentro que devolvería el número del partido.

Se puede usar cualquier llamada, por lo que podría usar una clase para rastrear la numeración:

 class FootnoteNumbers(object): def __init__(self, start=1): self.count = start - 1 def __call__(self, match): self.count += 1 return "{}".format(self.count) new_body_text = re.sub(pattern, FootnoteNumbers(), text) 

Ahora el estado del contador está contenido en la instancia de FootnoteNumbers() , y self.count se establecerá de nuevo cada vez que inicie una re.sub() .

Parece un buen ajuste para un cierre :

 def make_footnote_counter(start=1): count = [start - 1] # emulate nonlocal keyword def footnote_counter(match): count[0] += 1 return "%d" % count[0] return footnote_counter new_body_text = re.sub(pattern, make_footnote_counter(), text) 

Una variación y una solución exclusiva para Python-3:

 def make_create_footnote_numbers(start=1): count = start - 1 def create_footnote_numbers(match): nonlocal count count += 1 return "{}".format(count) return create_footnote_numbers new_body_text = re.sub(pattern, make_create_footnote_numbers(), text)