Análise de voo: como matar camelos corretamente 🐪

No âmbito da conversão universal de strings para snake_case, essa abordagem com regex é provavelmente a melhor opção:

import re

def to_snake_case(s: str) -> str:
s = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', s)
return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s).replace('-', '_').lower()


🧐 Como funciona?

1️⃣ re.sub('(.)([A-Z][a-z]+)', r'\1_\2', s) substitui cada letra maiúscula que precede uma minúscula pela mesma letra, mas com um sublinhado antes dela.

2️⃣ re.sub('([a-z0-9])([A-Z])', r'\1_\2', s) substitui cada letra maiúscula que precede uma minúscula ou dígito pela mesma letra, mas com um sublinhado antes dela.

3️⃣ Depois, tudo é convertido para minúsculas e os hífens são substituídos por sublinhados.

Mas vamos além do problema algorítmico e vejamos como resolver esse problema na prática. Se o projeto usa Pydantic, tudo isso já está escrito, testado em milhões de linhas de código e pronto para uso:

from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel, to_snake

class FrontendData(BaseModel):
model_config = ConfigDict(
alias_generator=to_camel, # Automaticamente espera camelCase na entrada
populate_by_name=True
)

python_talk: str # No código, trabalhamos com o ortodoxo snake_case

Sob o capô, há algoritmos refinados que consideram casos extremos, separadores não padrão e as fantasias mórbidas dos desenvolvedores de sistemas adjacentes.

E se o Pydantic não estiver no projeto, existem micro-bibliotecas como inflection que fazem o mesmo:
import inflection

inflection.underscore("CamelCaseAnd-kebab-case")
# -> 'camel_case_and_kebab_case'

inflection.camelize("python_talk", uppercase_first_letter=False)
# -> 'pythonTalk'


Conhecer algoritmos com regex é útil para passar em entrevistas de algoritmos e entender como as strings são analisadas. Mas conhecer as ferramentas é necessário para não levar para produção bicicletas caseiras que inevitavelmente quebrarão no primeiro payload torto.

#algoritmoentrevista