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


333

例:

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

28
要向另一个方向转换,请参阅另一个 stackoverflow问题。
内森

10
注意这NotCamelCase可是thisIs
马特·理查兹

5
@MattRichards这是一个有争议的问题。Wiki
NO_NAME 2015年

@MattRichards例如,在Java中,它们两者都使用,CamelCase用于命名类定义,而camelCase用于命名初始化变量。
暗的

Answers:


797

骆驼案到蛇案

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

蛇皮到骆驼皮

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

1
在以下情况下,该解决方案将失败:_test_Method,__test__Method,_Test,getHTTPresponseCode,__CamelCase和_Camel_Case。
freegnu 2011年

6
反过来呢?将转换not_camel_casenotCamelCase和/或NotCamelCase
john2x 2011年

9
为了在转换时避免双下划线,例如camel_Case,请添加以下行:s2.replace('__', '_')
Marcus Ahlberg

2
请注意,这不是非常可逆的。getHTTPResponseCode应该转换为get_h_t_t_p_response_code。getHttpResponseCode应该转换为get_http_response_code
K2xL 2015年

4
@AnmolSinghJaggi第一个正则表达式处理首字母缩写词的后一种情况,后跟另一个词(例如“ HTTPResponse”->“ HTTP_Response”),或者更常见的情况是初始小写字母后跟一个大写的词(例如“ getResponse”->“第二个正则表达式处理两个非首字母缩写的正常情况(例如“ ResponseCode”->“ Response_Code”),然后进行最终调用以小写所有内容。因此,“ getHTTPResponseCode”->“ getHTTP_ResponseCode”->“ get_HTTP_Response_Code”- >“ get_http_response_code”
杰夫·

188

包索引中有一个变形库可以为您处理这些事情。在这种情况下,您将寻找inflection.underscore()

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

44
我不明白,为什么有一个出色的库来执行此任务,人们为什么会投票赞成使用自定义函数。我们不应该重新发明轮子。
奥登2015年

88
@oden也许是因为添加一个全新的依赖项来完成单行功能是很脆弱的?
Cecil Curry 2015年

11
举例来说,请确保它过于矫kill过正。在更大的应用中,无需重新发明和混淆轮子。
布拉德·科赫

11
正则表达式返回很多“单行”,这就是为什么经过适当测试它不仅仅一行。
studgeek '17

12
@CecilCurry:我确定您是一个优秀的程序员,但是我不确定您是否没有考虑过这种情况,只需在此处查看其他答案即可。这就是为什么我总是选择一个库,因为这是更多开发人员的经验,而不仅仅是我自己。
Michael Scheper,

104

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

在大多数情况下,简单的表达([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'

要忽略第一个字符,只需添加后面的内容 (?!^)

>>> 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'

如果您想将ALLCaps分隔为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'

一切都取决于您想要什么,因此使用最适合您需求的解决方案,因为它不会太复杂。

欢乐!


1
最后一次迭代是最聪明的IMO。我花了一点时间才明白,它只是替换每个单词开头的单个字符-仅仅是因为这种方法与我自己想出的方法不同。做得很好。
贾斯汀·米勒

2
(?!^)表达式被称为后向(look-behind )让我感到困惑。除非我有什么遗漏,否则我们在这里真正想要的是负面的回望,应表示为(?<!^)。由于某些原因,我无法理解您的负面(?!^)
预兆

7
这不能很好地处理现有的下划线:"Camel2WARNING_Case_CASE"变为"camel2_warning_case__case"。您可以在后面添加一个(?<!_)负面的re.sub('((?<=[a-z0-9])[A-Z]|(?!^)(?<!_)[A-Z](?=[a-z]))', r'_\1', "Camel2WARNING_Case_CASE").lower()'camel2_warning_case_case'
表情

@Apteryx是的,(?!^)被错误地称为“ 向后看”,而应该被称为否定超前断言。正如这个很好的解释所示,否定的超前通常会您要搜索的表达式之后。所以,你可以想到的(?!^)是“寻找''那里<start of string>不跟随”。的确,后面的负面观察也是可行的:您可以将其(?<!^)视为“ ''<start of string>不存在的地方发现”。
纳撒尼尔·琼斯

17

stringcase是我为此准备的库;例如:

>>> from stringcase import pascalcase, snakecase
>>> snakecase('FooBarBaz')
'foo_bar_baz'
>>> pascalcase('foo_bar_baz')
'FooBarBaz'

11

我个人不确定在python中使用正则表达式的任何内容如何被描述为优雅。这里的大多数答案都只是在做“代码高尔夫”类型的RE技巧。优雅的编码应该很容易理解。

def to_snake_case(not_snake_case):
    final = ''
    for i in xrange(len(not_snake_case)):
        item = not_snake_case[i]
        if i < len(not_snake_case) - 1:
            next_char_will_be_underscored = (
                not_snake_case[i+1] == "_" or
                not_snake_case[i+1] == " " or
                not_snake_case[i+1].isupper()
            )
        if (item == " " or item == "_") and next_char_will_be_underscored:
            continue
        elif (item == " " or item == "_"):
            final += "_"
        elif item.isupper():
            final += "_"+item.lower()
        else:
            final += item
    if final[0] == "_":
        final = final[1:]
    return final

>>> to_snake_case("RegularExpressionsAreFunky")
'regular_expressions_are_funky'

>>> to_snake_case("RegularExpressionsAre Funky")
'regular_expressions_are_funky'

>>> to_snake_case("RegularExpressionsAre_Funky")
'regular_expressions_are_funky'

1
+=在字符串上几乎总是一个坏主意。追加到列表,''.join()最后。或者在这种情况下,只需在下划线处加入...
ThiefMaster

21
在几乎所有实用方式(包括可读性)上,单行正则表达式怎么都不比低效率的多行字符迭代和强力字符串调优具有天生的优越性?Python提供开箱即用的正则表达式支持是有原因的。
Cecil Curry 2015年

1
@CecilCurry-正则表达式非常复杂。见编译器和解析器,Python使用:svn.python.org/projects/python/trunk/Lib/sre_compile.pysvn.python.org/projects/python/trunk/Lib/sre_parse.py -简单的字符串操作一样这可能比RE的速度快得多。
埃文·博格斯特伦

1
+1。正则表达式可能是真正的CPU接收器,并且经过大量计算会大大降低性能。对于简单的任务,总是喜欢简单的功能。

4
“对于简单的任务,总是喜欢简单的功能”绝对是个好建议,但是这个答案既不是简单的功能,也不是优雅的功能。正则表达式可能会比较慢,但是默认使用像这样的复杂函数(也未经测试并且有很多潜在的错误点)完全是过早的优化
kevlarr

9

re如果可能,我宁愿避免:

def to_camelcase(s):
    return ''.join(['_' + c.lower() if c.isupper() else c for c in s]).lstrip('_')
>>> to_camelcase("ThisStringIsCamelCase")
'this_string_is_camel_case'

1
这是最紧凑的一种,它避免使用re库,而仅使用内置的str.methods仅在一行中进行处理!这类似于此答案,但是避免了if ... else通过简单地剥离可能添加的“ _”作为第一个字符来使用切片和附加功能。我最喜欢这个
colidyre

对于可接受的答案,6.81 µs ± 22.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)但对于此响应2.51 µs ± 25.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each),速度快2.5倍!喜欢这个!
WBAR

8
''.join('_'+c.lower() if c.isupper() else c for c in "DeathToCamelCase").strip('_')
re.sub("(.)([A-Z])", r'\1_\2', 'DeathToCamelCase').lower()

7

我认为此解决方案比以前的答案更直接:

import re

def convert (camel_input):
    words = re.findall(r'[A-Z]?[a-z]+|[A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$)|\d+', camel_input)
    return '_'.join(map(str.lower, words))


# Let's test it
test_strings = [
    'CamelCase',
    'camelCamelCase',
    'Camel2Camel2Case',
    'getHTTPResponseCode',
    'get200HTTPResponseCode',
    'getHTTP200ResponseCode',
    'HTTPResponseCode',
    'ResponseHTTP',
    'ResponseHTTP2',
    'Fun?!awesome',
    'Fun?!Awesome',
    '10CoolDudes',
    '20coolDudes'
]
for test_string in test_strings:
    print(convert(test_string))

哪个输出:

camel_case
camel_camel_case
camel_2_camel_2_case
get_http_response_code
get_200_http_response_code
get_http_200_response_code
http_response_code
response_http
response_http_2
fun_awesome
fun_awesome
10_cool_dudes
20_cool_dudes

正则表达式匹配三种模式:

  1. [A-Z]?[a-z]+:连续的小写字母,可以选择以大写字母开头。
  2. [A-Z]{2,}(?=[A-Z][a-z]|\d|\W|$):两个或多个连续的大写字母。如果在前一个大写字母后跟一个小写字母,它将使用前瞻性排除。
  3. \d+:连续数字。

通过使用,re.findall我们获得了单个“单词”的列表,这些单词可以转换为小写并带有下划线。


1
这里有一个很好的例子,可以独立地对数字进行标记。
math_law '18

1
损坏:convert(“ aB”)->'
a'– adw

5

我不知道为什么要同时使用两个.sub()调用?:)我不是regex专家,但是我将函数简化为这个函数,适合我的某些需求,我只需要一个解决方案即可将camelCasedVars从POST请求转换为vars_with_underscore:

def myFunc(...):
  return re.sub('(.)([A-Z]{1})', r'\1_\2', "iTriedToWriteNicely").lower()

它不能与getHTTPResponse之类的名称一起使用,因为我听说这是不好的命名约定(应该像getHttpResponse一样,很明显,记住这种形式要容易得多)。


我忘了提及,不需要'{1}',但是有时它有助于澄清一些模糊。
desper4do 2012年

2
-1:这是行不通的。尝试使用,例如'HTTPConnectionFactory',您的代码产生'h_tt_pconnection_factory',来自可接受答案的代码产生'http_connection_factory'
vartec

4

这是我的解决方案:

def un_camel(text):
    """ Converts a CamelCase name into an under_score name. 

        >>> un_camel('CamelCase')
        'camel_case'
        >>> un_camel('getHTTPResponseCode')
        'get_http_response_code'
    """
    result = []
    pos = 0
    while pos < len(text):
        if text[pos].isupper():
            if pos-1 > 0 and text[pos-1].islower() or pos-1 > 0 and \
            pos+1 < len(text) and text[pos+1].islower():
                result.append("_%s" % text[pos].lower())
            else:
                result.append(text[pos].lower())
        else:
            result.append(text[pos])
        pos += 1
    return "".join(result)

它支持评论中讨论的那些极端情况。例如,它将转换getHTTPResponseCodeget_http_response_code应有的状态。


7
-1,因为与使用正则表达式相比,它非常复杂。
Eric O Lebigot 09年

7
EOL,我敢肯定,很多非正则表达式的人都会不同意。
Evan Fosmark,2009年

在以下情况下该解决方案将失败:_Method,_test_Method,__ test__Method,getHTTPrespnseCode,__ get_HTTPresponseCode,_Camel_Case,_Test和_test_Method。
freegnu 2011年

3
@Evan,那些人将是糟糕的程序员。
Jesse Dhillon

3

有趣的是:

>>> def un_camel(input):
...     output = [input[0].lower()]
...     for c in input[1:]:
...             if c in ('ABCDEFGHIJKLMNOPQRSTUVWXYZ'):
...                     output.append('_')
...                     output.append(c.lower())
...             else:
...                     output.append(c)
...     return str.join('', output)
...
>>> un_camel("camel_case")
'camel_case'
>>> un_camel("CamelCase")
'camel_case'

或者,更多乐趣在于:

>>> un_camel = lambda i: i[0].lower() + str.join('', ("_" + c.lower() if c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" else c for c in i[1:]))
>>> un_camel("camel_case")
'camel_case'
>>> un_camel("CamelCase")
'camel_case'

3
c.isupper()而不是ABCEF ... Z中的c
Jimmy

1
Python没有正则表达式?快速的s / [az] \ K([AZ] [az])/ _ \ L $ 1 / g; Perl中的lc $ _'可以完成这项工作(尽管它不能很好地处理getHTTPResponseCode;但是应该可以将其命名为getHttpResponseCode)
jrockway

5
str.join已被弃用了好久。使用''.join(..)代替。
John Fouhy

jrockway:通过“ re”模块,它确实具有正则表达式。使用正则表达式而不是此处发布的方法进行这项工作应该不会太困难。
马修·伊瑟林

Python noob在这里,但是为什么返回str.join('',output)?只是要创建副本?
Tarks

3

使用正则表达式可能是最短的,但是此解决方案更具可读性:

def to_snake_case(s):
    snake = "".join(["_"+c.lower() if c.isupper() else c for c in s])
    return snake[1:] if snake.startswith("_") else snake

@blueyed完全无关,这个问题与django无关。
3k-

这只是一个示例,例如HTTPResponseCode,由stackoverflow.com/a/23561109/15690处理。
2015年

3

如此众多的复杂方法...只需找到所有“ Titled”组并将其小写变体加下划线即可。

>>> import re
>>> def camel_to_snake(string):
...     groups = re.findall('([A-z0-9][a-z]*)', string)
...     return '_'.join([i.lower() for i in groups])
...
>>> camel_to_snake('ABCPingPongByTheWay2KWhereIsOurBorderlands3???')
'a_b_c_ping_pong_by_the_way_2_k_where_is_our_borderlands_3'

如果您不想像组的第一个字符或单独的组那样输入数字,则可以使用([A-z][a-z0-9]*)遮罩。



2

这不是一个优雅的方法,它是简单状态机(位域状态机)的非常“低级”实现,可能是解决此问题的最反Python模式,但是re模块也实现了一个太复杂的状态机来解决此简单问题任务,所以我认为这是一个很好的解决方案。

def splitSymbol(s):
    si, ci, state = 0, 0, 0 # start_index, current_index 
    '''
        state bits:
        0: no yields
        1: lower yields
        2: lower yields - 1
        4: upper yields
        8: digit yields
        16: other yields
        32 : upper sequence mark
    '''
    for c in s:

        if c.islower():
            if state & 1:
                yield s[si:ci]
                si = ci
            elif state & 2:
                yield s[si:ci - 1]
                si = ci - 1
            state = 4 | 8 | 16
            ci += 1

        elif c.isupper():
            if state & 4:
                yield s[si:ci]
                si = ci
            if state & 32:
                state = 2 | 8 | 16 | 32
            else:
                state = 8 | 16 | 32

            ci += 1

        elif c.isdigit():
            if state & 8:
                yield s[si:ci]
                si = ci
            state = 1 | 4 | 16
            ci += 1

        else:
            if state & 16:
                yield s[si:ci]
            state = 0
            ci += 1  # eat ci
            si = ci   
        print(' : ', c, bin(state))
    if state:
        yield s[si:ci] 


def camelcaseToUnderscore(s):
    return '_'.join(splitSymbol(s)) 

splitsymbol可以解析所有情况类型:UpperSEQUENCEInterleaved,under_score,BIG_SYMBOLS和cammelCasedMethods

我希望它有用


1
吓人的,但是它的运行速度比我机器上的regex方法快3倍。:)
jdiaz5513


1

看看优秀的Schematics库

https://github.com/schematics/schematics

它允许您创建可以从python序列化/反序列化为Java语言风格的类型化数据结构,例如:

class MapPrice(Model):
    price_before_vat = DecimalType(serialized_name='priceBeforeVat')
    vat_rate = DecimalType(serialized_name='vatRate')
    vat = DecimalType()
    total_price = DecimalType(serialized_name='totalPrice')

1

这个简单的方法应该可以完成以下工作:

import re

def convert(name):
    return re.sub(r'([A-Z]*)([A-Z][a-z]+)', lambda x: (x.group(1) + '_' if x.group(1) else '') + x.group(2) + '_', name).rstrip('_').lower()
  • 我们要查找大写字母,该大写字母后跟任意数量(或零个)的大写字母,后跟任意数量的小写字符。
  • 下划线位于该组中最后一个大写字母的出现之前,并且如果在其他大写字母之前出现,可以在该大写字母之前放置一个下划线。
  • 如果有结尾的下划线,请将其删除。
  • 最后,将整个结果字符串更改为小写。

(取自此处在线查看工作示例


这是对另一个问题(如何转换驼峰大小写)的答案。
贾斯汀

1

哇,我只是从django片段中偷了这个。参考http://djangosnippets.org/snippets/585/

相当优雅

camelcase_to_underscore = lambda str: re.sub(r'(?<=[a-z])[A-Z]|[A-Z](?=[^A-Z])', r'_\g<0>', str).lower().strip('_')

例:

camelcase_to_underscore('ThisUser')

返回值:

'this_user'

正则演示


1
使用str作为局部变量名称的错误格式。
freegnu 2011年

如果字符串的开头或结尾有下划线,并且在大写字母之前有任何下划线,则此操作将失败。
freegnu 2011年

犯规考虑到数字😬
villy393

0

一个使用正则表达式的可怕示例(您可以轻松清理掉:)):

def f(s):
    return s.group(1).lower() + "_" + s.group(2).lower()

p = re.compile("([A-Z]+[a-z]+)([A-Z]?)")
print p.sub(f, "CamelCase")
print p.sub(f, "getHTTPResponseCode")

虽然适用于getHTTPResponseCode!

或者,使用lambda:

p = re.compile("([A-Z]+[a-z]+)([A-Z]?)")
print p.sub(lambda x: x.group(1).lower() + "_" + x.group(2).lower(), "CamelCase")
print p.sub(lambda x: x.group(1).lower() + "_" + x.group(2).lower(), "getHTTPResponseCode")

编辑:还应该很容易看到,对于“测试”这样的情况,还有改进的空间,因为下划线是无条件插入的。


0

我做了一些更改以制表符分隔的文件中的标头的方法。我省略了仅编辑文件第一行的部分。您可以使用re库轻松将其适应Python。这还包括分隔数字(但将数字保持在一起)。我分两个步骤进行操作,因为这比告诉它不要在行或制表符的开头添加下划线要容易。

步骤一...查找大写字母或整数,再加上小写字母,并在其前加上下划线:

搜索:

([a-z]+)([A-Z]|[0-9]+)

替代:

\1_\l\2/

第二步...执行以上操作,然后再次运行以将所有大写字母转换为小写:

搜索:

([A-Z])

替换(反斜杠,小写L,反斜杠一个):

\l\1

0

我一直在寻找解决同一问题的方法,只是我需要一条链子。例如

"CamelCamelCamelCase" -> "Camel-camel-camel-case"

从这里不错的两个词解决方案开始,我想到了以下内容:

"-".join(x.group(1).lower() if x.group(2) is None else x.group(1) \
         for x in re.finditer("((^.[^A-Z]+)|([A-Z][^A-Z]+))", "stringToSplit"))

大多数复杂的逻辑是避免小写第一个单词。如果您不介意更改第一个单词,这是一个更简单的版本:

"-".join(x.group(1).lower() for x in re.finditer("(^[^A-Z]+|[A-Z][^A-Z]+)", "stringToSplit"))

当然,您可以预编译正则表达式,也可以使用下划线代替连字符,如其他解决方案中所述。


0

简洁而没有正则表达式,但是HTTPResponseCode => httpresponse_code:

def from_camel(name):
    """
    ThisIsCamelCase ==> this_is_camel_case
    """
    name = name.replace("_", "")
    _cas = lambda _x : [_i.isupper() for _i in _x]
    seq = zip(_cas(name[1:-1]), _cas(name[2:]))
    ss = [_x + 1 for _x, (_i, _j) in enumerate(seq) if (_i, _j) == (False, True)]
    return "".join([ch + "_" if _x in ss else ch for _x, ch in numerate(name.lower())])

0

没有任何库:

def camelify(out):
    return (''.join(["_"+x.lower() if i<len(out)-1 and x.isupper() and out[i+1].islower()
         else x.lower()+"_" if i<len(out)-1 and x.islower() and out[i+1].isupper()
         else x.lower() for i,x in enumerate(list(out))])).lstrip('_').replace('__','_')

有点重,但是

CamelCamelCamelCase ->  camel_camel_camel_case
HTTPRequest         ->  http_request
GetHTTPRequest      ->  get_http_request
getHTTPRequest      ->  get_http_request

0

这个网站上提出的非常好的RegEx :

(?<!^)(?=[A-Z])

如果python有一个String Split方法,它应该可以工作...

在Java中:

String s = "loremIpsum";
words = s.split("(?&#60;!^)(?=[A-Z])");

不幸的是,Python正则表达式模块不支持(从3.6版开始)对零长度匹配进行拆分。
rspeed

0
def convert(name):
    return reduce(
        lambda x, y: x + ('_' if y.isupper() else '') + y, 
        name
    ).lower()

而且,如果我们需要用一个已经没有名称的输入来覆盖一个案例:

def convert(name):
    return reduce(
        lambda x, y: x + ('_' if y.isupper() and not x.endswith('_') else '') + y, 
        name
    ).lower()

0

万一有人需要转换完整的源文件,可以使用以下脚本来完成。

# Copy and paste your camel case code in the string below
camelCaseCode ="""
    cv2.Matx33d ComputeZoomMatrix(const cv2.Point2d & zoomCenter, double zoomRatio)
    {
      auto mat = cv2.Matx33d::eye();
      mat(0, 0) = zoomRatio;
      mat(1, 1) = zoomRatio;
      mat(0, 2) = zoomCenter.x * (1. - zoomRatio);
      mat(1, 2) = zoomCenter.y * (1. - zoomRatio);
      return mat;
    }
"""

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

def lines(str):
    return str.split("\n")

def unlines(lst):
    return "\n".join(lst)

def words(str):
    return str.split(" ")

def unwords(lst):
    return " ".join(lst)

def map_partial(function):
    return lambda values : [  function(v) for v in values]

import functools
def compose(*functions):
    return functools.reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)

snake_case_code = compose(
    unlines ,
    map_partial(unwords),
    map_partial(map_partial(snake_case)),
    map_partial(words),
    lines
)
print(snake_case_code(camelCaseCode))

-1

我已经很幸运了:

import re
def camelcase_to_underscore(s):
    return re.sub(r'(^|[a-z])([A-Z])',
                  lambda m: '_'.join([i.lower() for i in m.groups() if i]),
                  s)

如果您愿意的话,显然可以对速度进行点点优化。

import re

CC2US_RE = re.compile(r'(^|[a-z])([A-Z])')

def _replace(match):
    return '_'.join([i.lower() for i in match.groups() if i])

def camelcase_to_underscores(s):
    return CC2US_RE.sub(_replace, s)

-1
def convert(camel_str):
    temp_list = []
    for letter in camel_str:
        if letter.islower():
            temp_list.append(letter)
        else:
            temp_list.append('_')
            temp_list.append(letter)
    result = "".join(temp_list)
    return result.lower()

-3

使用:str.capitalize()将字符串的第一个字母(包含在变量str中)转换为大写字母并返回整个字符串。

示例:命令:“ hello” .capitalize()输出:Hello


这与问题无关-OP需要CamelCase-> snake_case,而不是大写。
布拉德·科赫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.