将蛇形命名法(snake_case)转换为小驼峰命名法(lowerCamelCase)。

118
什么是将蛇形命名法(my_string)转换为小驼峰命名法(myString)的好方法?在Python 2.7中,有什么明显的解决方案可以通过下划线分割字符串,将每个单词的首字母大写,并重新拼接在一起。
然而,我对其他更惯用的解决方案或者使用正则表达式(RegExp)来实现这个目标(带有一些大小写修改器)很感兴趣。

据我所知,目前没有现成的解决方案可以实现这一点。你尝试过自己实现吗? - Frédéric Hamidi
我编辑了我的问题,我知道没有内置的实现,我想找到一个好的实现。 - luca
我认为这个问题在任何方面都不是“离题”的。 - 0xc0de
16个回答

215
def to_camel_case(snake_str):
    return "".join(x.capitalize() for x in snake_str.lower().split("_"))

def to_lower_camel_case(snake_str):
    # We capitalize the first letter of each component except the first one
    # with the 'capitalize' method and join them together.
    camel_string = to_camel_case(snake_str)
    return snake_str[0].lower() + camel_string[1:]

例子:

In [11]: to_lower_camel_case('snake_case')
Out[11]: 'snakeCase'

In [12]: to_lower_camel_case('SNAKE_Case')
Out[12]: 'snakeCase'

In [13]: to_lower_camel_case('SNAKE_CASE')
Out[13]: 'snakeCase'

11
驼峰式命名适用于哪些其他数据类型? - jbaiter
22
嗯,这并不是符合Python惯用写法的方式,通常遵循“宁愿请求原谅也不要事先征得许可”的原则。如果你想要类型安全,可以在版本3.5及以上加入类型提示。但对于像这样明确简单的函数(除了字符串还能有什么其他驼峰命名的对象?),使用if-else进行类型检查只是我看来非常糟糕的风格和冗余操作。 - jbaiter
2
我想在这里支持jbaiter的观点。to_camel_case并不负责确保输入是一个字符串,它的责任是由调用代码来承担。传递一个非字符串将引发异常,这是好事情。这就是异常的作用。 - kylebebak
4
有点特殊情况,但如果你希望 _bar 变成 bar 而不是 Bar,则需要进行微小的调整:components = snake_str.lstrip('_').split('_') - bigh_29
1
我认为调用 str.capitalize() 比调用 str.title() 更加准确,因为 title() 暗示了给定字符串中有多个单词,但是在任何组成部分中都不应该有空格。 - sandor
显示剩余2条评论

29

以下是另一种方法,仅适用于Python 3.5及更高版本:

def camel(snake_str):
    first, *others = snake_str.split('_')
    return ''.join([first.lower(), *map(str.title, others)])

在使用生成器可以解决问题的情况下,不要使用列表推导式(例如,在这里join(...)join([...])更好,因为它可以在不创建列表的情况下工作)。 - Vedran Šego
3
您说得完全正确,但是在这种特定情况下不适用,因为传递给join方法的不是一个推导式而是一个常规列表。如果您想避免创建内存中的列表,可以使用itertools.chain,但是如果在将蛇形命名法转换为驼峰命名法时您担心内存占用问题,那么您有更大的问题要处理。;-) - Berislav Lopac
抱歉,我读错了(因为我一开始找的是PascalCase而不是camelCase)。不,这样就可以了。 - Vedran Šego

23

虽然有点晚了,但我几天前在/r/python上发现了这篇文章:

pip install pyhumps

然后你只需要执行:

import humps

humps.camelize('jack_in_the_box')  # jackInTheBox
# or
humps.decamelize('rubyTuesdays')  # ruby_tuesdays
# or
humps.pascalize('red_robin')  # RedRobin

1
这是一个不错的解决方案,而且如果你传入一个字典,它会将键转换为驼峰式,但保留值。这对于在Python中构建API但希望JSON响应更加JavaScript友好的人来说非常完美。 - Antoine Wood

13

另一条简短的内容

def to_camel_case(snake_string):
    return snake_string.title().replace("_", "")

8
First char is Upper Case. - SiHa
如果您想将其转换为类名,这将非常有用。 - Ramon Dias
1
虽然 OP 要求使用小驼峰命名法,但这实际上是在搜索“将蛇形命名法转换为驼峰命名法 Python”时出现的第一个 stackoverflow 示例。这正是我想要的,所以我很高兴它在这里。 - Steven C. Howell

9

必要的一行简介:

import string

def to_camel_case(s):
    return s[0].lower() + string.capwords(s, sep='_').replace('_', '')[1:] if s else s

当使用前导下划线时(第一个字母被省略),此方法会失败。 - siebz0r
6
更简洁的写法:return re.sub(r'_([a-z])', lambda x: x.group(1).upper(), name) - Mathieu Rodic

5
>>> snake_case = "this_is_a_snake_case_string"
>>> l = snake_case.split("_")
>>> print l[0] + "".join(map(str.capitalize, l[1:]))
'thisIsASnakeCaseString'

4

对于代码压缩迷们...

''.join((wd.title() if i else wd) for (i,wd) in enumerate(string.split('_')))

3
建立在Steve的回答之上,这个版本应该可以工作:
def to_camel_case(snake_case_string):
    titleCaseVersion =  snake_case_string.title().replace("_", "")
    camelCaseVersion = titleCaseVersion[0].lower() + titleCaseVersion[1:]
    return camelCaseVersion

3

这个太简单了吗?

snake_case 已经是小写的了。 my_string

所以如果我们将字符串标题化并去掉下划线 MyString

然后用原始的 m 替换第一个字符 M,我们就完成了。

scase = "my_string"
ccase = scase[0] + scase.title().replace('_', '')[1:]

输出: myString

2

我个人使用这个解决方案,因为它是一个推进的转换:

from functools import reduce

def camelize(snake_string: str) -> str:
    return reduce(lambda x, y: x + y.capitalize(), snake_string.split('_'))

如果有一个前导下划线,这个解决方案会将第一个单词大写。 - Rob Smallshire

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接