例子:

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

当前回答

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

其他回答

避免使用库和正则表达式:

def camel_to_snake(s):
    return ''.join(['_'+c.lower() if c.isupper() else c for c in s]).lstrip('_')
>>> camel_to_snake('ThisIsMyString')
'this_is_my_string'

我也在寻找同样问题的解决方案,只不过我需要一条链子;如。

"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"))

当然,您可以预先编译正则表达式,或者像其他解决方案中讨论的那样,使用下划线而不是连字符连接正则表达式。

以下是我的解决方案:

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)

它支持评论中讨论的那些极端情况。例如,它会像它应该的那样将getHTTPResponseCode转换为get_http_response_code。

这不是一个优雅的方法,是一个非常“低级”的实现一个简单的状态机(位域状态机),可能是最反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

我希望它是有用的

轻度改编自https://stackoverflow.com/users/267781/matth 谁使用发电机。

def uncamelize(s):
    buff, l = '', []
    for ltr in s:
        if ltr.isupper():
            if buff:
                l.append(buff)
                buff = ''
        buff += ltr
    l.append(buff)
    return '_'.join(l).lower()