Преобразование в snake case на Python

PythonPythonBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В Python "snake case" (змеиный регистр) представляет собой соглашение об именовании, при котором слова разделяются подчеркиваниями. Этот стиль именования обычно используется для переменных, функций и других идентификаторов в Python. Например, calculate_total_price и user_authentication имеют формат snake case.

Иногда мы можем столкнуться со строками, имеющими другие форматы, такие как camelCase, PascalCase или даже строками с пробелами и дефисами. В таких случаях нам нужно преобразовать эти строки в snake case для обеспечения единообразия в нашем коде.

В этом лабораторном занятии (LabEx) вы научитесь писать функцию на Python, которая преобразует строки из различных форматов в snake case.

Понимание проблемы

Прежде чем мы напишем функцию для преобразования в snake case, давайте разберемся, что нам нужно сделать:

  1. Мы должны преобразовать строку из любого формата в snake case.
  2. Snake case означает, что все буквы должны быть в нижнем регистре, а слова разделены подчеркиваниями.
  3. Мы должны обрабатывать различные форматы входных данных:
    • camelCase (например, camelCasecamel_case)
    • Строки с пробелами (например, some textsome_text)
    • Строки с смешанным форматированием (например, с дефисами, подчеркиваниями и смешанным регистром)

Начнем с создания нового файла Python для нашей функции snake case. В WebIDE перейдите в директорию проекта и создайте новый файл с именем snake_case.py:

## This function will convert a string to snake case
def snake(s):
    ## We'll implement this function step by step
    pass  ## Placeholder for now

## Test with a simple example
if __name__ == "__main__":
    test_string = "helloWorld"
    result = snake(test_string)
    print(f"Original: {test_string}")
    print(f"Snake case: {result}")

Сохраните этот файл. На следующем шаге мы начнем реализацию функции.

Пока что давайте запустим нашу заглушку функции, чтобы убедиться, что наш файл настроен правильно. Откройте терминал и запустите:

python3 ~/project/snake_case.py
python-prompt

Вы должны увидеть вывод, похожий на следующий:

Original: helloWorld
Snake case: None

Результат равен None, потому что наша функция в настоящее время просто возвращает значение по умолчанию Python None. На следующем шаге мы добавим фактическую логику преобразования.

Использование регулярных выражений для сопоставления шаблонов

Для преобразования строк в snake case мы будем использовать регулярные выражения (regex), чтобы определить границы слов. Модуль re в Python предоставляет мощные возможности по сопоставлению шаблонов, которые мы можем использовать для этой задачи.

Давайте обновим нашу функцию, чтобы она могла обрабатывать строки в формате camelCase:

  1. Сначала нам нужно определить шаблон, когда строчная буква следует за заглавной (как в "camelCase").
  2. Затем мы вставим пробел между ними.
  3. Наконец, мы преобразуем все в нижний регистр и заменим пробелы на подчеркивания.

Обновите файл snake_case.py с этой улучшенной функцией:

import re

def snake(s):
    ## Replace pattern of a lowercase letter followed by uppercase with lowercase, space, uppercase
    s1 = re.sub('([a-z])([A-Z])', r'\1 \2', s)

    ## Replace spaces with underscores and convert to lowercase
    return s1.lower().replace(' ', '_')

## Test with a simple example
if __name__ == "__main__":
    test_string = "helloWorld"
    result = snake(test_string)
    print(f"Original: {test_string}")
    print(f"Snake case: {result}")

Давайте разберем, что делает эта функция:

  • re.sub('([a-z])([A-Z])', r'\1 \2', s) ищет шаблоны, где строчная буква ([a-z]) следует за заглавной буквой ([A-Z]). Затем он заменяет этот шаблон на те же буквы, но добавляет пробел между ними с помощью \1 и \2, которые ссылаются на захваченные группы.
  • Затем мы преобразуем все в нижний регистр с помощью lower() и заменяем пробелы на подчеркивания.

Запустите скрипт еще раз, чтобы проверить, работает ли он для строк в формате camelCase:

python3 ~/project/snake_case.py

Теперь вывод должен быть таким:

Original: helloWorld
Snake case: hello_world

Отлично! Теперь наша функция может обрабатывать строки в формате camelCase. На следующем шаге мы усовершенствуем ее, чтобы она могла обрабатывать более сложные случаи.

Обработка более сложных шаблонов

Наша текущая функция работает для camelCase, но нам нужно улучшить ее, чтобы она могла обрабатывать дополнительные шаблоны, такие как:

  1. PascalCase (например, HelloWorld)
  2. Строки с дефисами (например, hello-world)
  3. Строки, которые уже содержат подчеркивания (например, hello_world)

Давайте обновим нашу функцию, чтобы она могла обрабатывать эти случаи:

import re

def snake(s):
    ## Replace hyphens with spaces
    s = s.replace('-', ' ')

    ## Handle PascalCase pattern (sequences of uppercase letters)
    s = re.sub('([A-Z]+)', r' \1', s)

    ## Handle camelCase pattern (lowercase followed by uppercase)
    s = re.sub('([a-z])([A-Z])', r'\1 \2', s)

    ## Split by spaces, join with underscores, and convert to lowercase
    return '_'.join(s.split()).lower()

## Test with multiple examples
if __name__ == "__main__":
    test_strings = [
        "helloWorld",
        "HelloWorld",
        "hello-world",
        "hello_world",
        "some text"
    ]

    for test in test_strings:
        result = snake(test)
        print(f"Original: {test}")
        print(f"Snake case: {result}")
        print("-" * 20)

Улучшения, которые мы внесли:

  1. Сначала мы заменяем все дефисы на пробелы.
  2. Новое регулярное выражение re.sub('([A-Z]+)', r' \1', s) добавляет пробел перед любой последовательностью заглавных букв, что помогает обработать PascalCase.
  3. Мы сохраняем наше регулярное выражение для обработки camelCase.
  4. Наконец, мы разбиваем строку по пробелам, объединяем ее с использованием подчеркиваний и преобразуем в нижний регистр, что позволяет обработать любые оставшиеся пробелы и обеспечить последовательный вывод.

Запустите скрипт, чтобы протестировать его с различными форматами входных данных:

python3 ~/project/snake_case.py

Вы должны увидеть вывод, похожий на следующий:

Original: helloWorld
Snake case: hello_world
--------------------
Original: HelloWorld
Snake case: hello_world
--------------------
Original: hello-world
Snake case: hello_world
--------------------
Original: hello_world
Snake case: hello_world
--------------------
Original: some text
Snake case: some_text
--------------------

Наша функция теперь более надежная и может обрабатывать различные форматы входных данных. На следующем шаге мы внесем последние усовершенствования и протестируем ее на полном наборе тестов.

Финальная реализация и тестирование

Теперь давайте завершим реализацию, чтобы обработать все необходимые случаи, и проверим, что она проходит все тестовые случаи.

Обновите файл snake_case.py с финальной реализацией:

import re

def snake(s):
    ## Replace hyphens with spaces
    s = s.replace('-', ' ')

    ## Handle PascalCase pattern
    s = re.sub('([A-Z][a-z]+)', r' \1', s)

    ## Handle sequences of uppercase letters
    s = re.sub('([A-Z]+)', r' \1', s)

    ## Split by whitespace and join with underscores
    return '_'.join(s.split()).lower()

## Test with a complex example
if __name__ == "__main__":
    test_string = "some-mixed_string With spaces_underscores-and-hyphens"
    result = snake(test_string)
    print(f"Original: {test_string}")
    print(f"Snake case: {result}")

В этой финальной реализации:

  1. Дефисы заменяются на пробелы.
  2. Перед шаблонами типа "Word" добавляется пробел с помощью re.sub('([A-Z][a-z]+)', r' \1', s).
  3. Перед последовательностями заглавных букв добавляется пробел с помощью re.sub('([A-Z]+)', r' \1', s).
  4. Строка разбивается по пробелам, объединяется с использованием подчеркиваний и преобразуется в нижний регистр.

Теперь давайте запустим нашу функцию на наборе тестов, созданном на этапе настройки:

python3 ~/project/test_snake.py

Если ваша реализация правильная, вы должны увидеть:

All tests passed! Your snake case function works correctly.

Поздравляем! Вы успешно реализовали надежную функцию преобразования в snake case, которая может обрабатывать различные форматы входных данных.

Давайте убедимся, что наша функция точно соответствует спецификации, протестировав ее на примерах из исходной задачи:

## Add this to the end of your snake_case.py file:
if __name__ == "__main__":
    examples = [
        'camelCase',
      'some text',
      'some-mixed_string With spaces_underscores-and-hyphens',
        'AllThe-small Things'
    ]

    for ex in examples:
        result = snake(ex)
        print(f"Original: {ex}")
        print(f"Snake case: {result}")
        print("-" * 20)

Запустите обновленный скрипт:

python3 ~/project/snake_case.py

Вы должны увидеть, что все примеры правильно преобразуются в snake case:

Original: some-mixed_string With spaces_underscores-and-hyphens
Snake case: some_mixed_string_with_spaces_underscores_and_hyphens
Original: camelCase
Snake case: camel_case
--------------------
Original: some text
Snake case: some_text
--------------------
Original: some-mixed_string With spaces_underscores-and-hyphens
Snake case: some_mixed_string_with_spaces_underscores_and_hyphens
--------------------
Original: AllThe-small Things
Snake case: all_the_small_things
--------------------

Резюме

В этом лабораторном занятии вы научились создавать функцию на Python, которая преобразует строки из различных форматов в snake case. Вот, что вы достигли:

  1. Вы узнали, как регулярные выражения можно использовать для сопоставления шаблонов и преобразования строк.
  2. Вы реализовали функцию, которая может обрабатывать разные форматы входных данных:
    • camelCase (например, camelCasecamel_case)
    • PascalCase (например, HelloWorldhello_world)
    • Строки с пробелами (например, some textsome_text)
    • Строки с дефисами (например, hello-worldhello_world)
    • Смешанные форматы с различными разделителями и регистром букв

Основные техники, которые вы использовали:

  • Регулярные выражения с группами захвата с использованием re.sub()
  • Методы строк, такие как replace(), lower(), split() и join()
  • Распознавание шаблонов для разных соглашений об именовании

Эти навыки ценны для очистки данных, обработки текстовых входных данных и соблюдения единых стандартов кодирования. Возможность преобразовывать между разными форматами регистров особенно полезна при работе с API или библиотеками, которые используют разные соглашения об именовании.