优雅的Python函数将CamelCase转换为snake_case?

332 投票
29 回答
369658 浏览
提问于 2025-04-15 13:07

示例:

>>> convert('CamelCase')
'camel_case'

29 个回答

159

我不知道为什么这些东西都这么复杂。

在大多数情况下,简单的表达式 ([A-Z]+) 就能解决问题。

>>> re.sub('([A-Z]+)', r'_\1','CamelCase').lower()
'_camel_case'  
>>> re.sub('([A-Z]+)', r'_\1','camelCase').lower()
'camel_case'
>>> re.sub('([A-Z]+)', r'_\1','camel2Case2').lower()
'camel2_case2'
>>> re.sub('([A-Z]+)', r'_\1','camelCamelCase').lower()
'camel_camel_case'
>>> re.sub('([A-Z]+)', r'_\1','getHTTPResponseCode').lower()
'get_httpresponse_code'

如果你想忽略第一个字符,只需加上一个向后看(look behind) (?!^)

>>> re.sub('(?!^)([A-Z]+)', r'_\1','CamelCase').lower()
'camel_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','CamelCamelCase').lower()
'camel_camel_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','Camel2Camel2Case').lower()
'camel2_camel2_case'
>>> re.sub('(?!^)([A-Z]+)', r'_\1','getHTTPResponseCode').lower()
'get_httpresponse_code'

如果你想把全大写的字母分开成 all_caps,并且希望字符串中包含数字,你其实不需要分开两次处理,只需使用 |。这个表达式 ((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z])) 几乎可以处理所有情况。

>>> a = re.compile('((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))')
>>> a.sub(r'_\1', 'getHTTPResponseCode').lower()
'get_http_response_code'
>>> a.sub(r'_\1', 'get2HTTPResponseCode').lower()
'get2_http_response_code'
>>> a.sub(r'_\1', 'get2HTTPResponse123Code').lower()
'get2_http_response123_code'
>>> a.sub(r'_\1', 'HTTPResponseCode').lower()
'http_response_code'
>>> a.sub(r'_\1', 'HTTPResponseCodeXYZ').lower()
'http_response_code_xyz'

这完全取决于你想要什么,所以选择最适合你需求的解决方案,不要让事情变得过于复杂。

祝你好运!

305

在这个软件包索引里,有一个叫做 inflection 的库,它可以帮你处理这些事情。这里你需要用到的是 inflection.underscore()

>>> inflection.underscore('CamelCase')
'camel_case'
1187

驼峰命名法转下划线命名法

import re

name = 'CamelCaseName'
name = re.sub(r'(?<!^)(?=[A-Z])', '_', name).lower()
print(name)  # camel_case_name

如果你经常需要这样做,而上面的方式比较慢,可以提前编译正则表达式:

pattern = re.compile(r'(?<!^)(?=[A-Z])')
name = pattern.sub('_', name).lower()

为了处理一些更复杂的情况(这种情况是不可逆的):

def camel_to_snake(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('camel2_camel2_case'))  # camel2_camel2_case
print(camel_to_snake('getHTTPResponseCode'))  # get_http_response_code
print(camel_to_snake('HTTPResponseCodeXYZ'))  # http_response_code_xyz

还要处理包含两个下划线或更多的情况:

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

下划线命名法转帕斯卡命名法

name = 'snake_case_name'
name = ''.join(word.title() for word in name.split('_'))
print(name)  # SnakeCaseName

撰写回答