Explain Codes LogoExplain Codes Logo

Elegant Python function to convert CamelCase to snake_case?

python
prompt-engineering
functions
list-comprehension
Nikita BarsukovbyNikita Barsukov·Dec 12, 2024
TLDR

To swiftly convert CamelCase to snake_case, use regular expressions (regex):

import re def camel_to_snake(name): return re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower() # Example: print(camel_to_snake('NoMoreCamel')) # no_more_camel

Here we deploy re.sub() to insert an underscore _ before each upper case letter (except the first one) and then .lower() to transform all characters to lowercase.

Go beyond regex: Libraries and Edge Cases

String transformation with inflection library

The inflection library comes in handy for more sophisticated string manipulations, effortlessly converting CamelCase to snake_case:

import inflection print(inflection.underscore('CamelCaseAutomagic')) # camel_case_automagic

No need to invent the wheel when we have highly efficient libraries!

Taming rogue ALLCAPS and numerics

Strings that include all capital letters or numeric values might render unexpected results. Let's craft a specific regex pattern to handle these wild beasts:

def camel_to_snake_advanced(name): name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower() print(camel_to_snake_advanced('OMGThisIs911')) # omg_this_is_911

Watch out, ALLCAPS on the loose!

Leverage the stringcase library

Yet again, a library to save the day! The stringcase library lets you convert CamelCase to snake_case in a blink of an eye:

import stringcase print(stringcase.snakecase('CamelCaseOnSteroids')) # camel_case_on_steroids

As simple as Python's print("Hello, World!").

Unwanted leading underscores? No more!

In some scenarios, conversion might lead to unexpected leading undescores. Here comes lstrip to the rescue:

converted = '_pesky_leading_underscore'.lstrip('_') # 'pesky_leading_underscore'

Who let this underscore in?!

Pythonic Approach: When elegance meets functionality

List comprehension and join method

An elegant and native approach would be the combination of list comprehension and the join method:

def camel_to_snake_pythonic(name): return ''.join(['_' + i.lower() if i.isupper() else i for i in name]).lstrip('_') print(camel_to_snake_pythonic('ThisOneIsFun')) # this_one_is_fun

Pythonic solutions are like fine wine, they age beautifully! 🍷

Increase performance with precompiled regex patterns

In cases where performance is key, precompiling the regex pattern can boost efficiency:

pattern = re.compile(r'(?<!^)(?=[A-Z])') def camel_to_snake_precompiled(name, _pattern=pattern): return _pattern.sub('_', name).lower() print(camel_to_snake_precompiled('FastAndFurious')) # fast_and_furious

Fast as a Ferrar...I mean, as a precompiled regex.

Advanced Techniques: Handling ambiguous scenarios

All you acronyms, line up!

Ever stumbled upon tricky acronyms within CamelCase? Take manual charge or resort to libraries that recognize and handle acronyms appropriately:

print(camel_to_snake_advanced('NASAExplorer')) # nasa_explorer (not n_a_s_a_explorer)

Houston, we've solved the problem.

Abbreviations in action

Just like acronyms, abbreviations may trip the converter. Special attention handles these gracefully, avoiding undesired underscores:

print(camel_to_snake_advanced('HTTPRequestAPI')) # http_request_api

That's HTTPeace of cake!

PEP-8: The guardian of Python's clarity

Manual review sometimes is key to preserve clarity and consistency. Automatic methods occasionally fall short to follow Python's PEP-8 style guidelines.