CamelCase を snake_case に変換するエレガントな Python 関数はありますか? 質問する

CamelCase を snake_case に変換するエレガントな Python 関数はありますか? 質問する

例:

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

ベストアンサー1

キャメルケースからスネークケースへ

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

これと直後の正規表現はゼロ幅一致を使用しますが、これは Python 3.6 以前では正しく処理されないことに注意してください。古い EOL Python をサポートする必要がある場合は、先読み/後読みを使用しない代替手段については、以下を参照してください。

"HTTPHeader"への変換を避けたい場合は"h_t_t_p_header"、正規表現の代替で次のバリアントを使用できます。

pattern = re.compile(r"(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])")
name = pattern.sub('_', name).lower()

見る翻訳元テストケース用(末尾に小文字を含まない)。

?xまたは を使用すると読みやすさが向上しますre.X

pattern = re.compile(
    r"""
        (?<=[a-z])      # preceded by lowercase
        (?=[A-Z])       # followed by uppercase
        |               #   OR
        (?<[A-Z])       # preceded by lowercase
        (?=[A-Z][a-z])  # followed by uppercase, then lowercase
    """,
    re.X,
)

を使用する場合regexモジュールの代わりにre、より読みやすい POSIX 文字クラス (ASCII に限定されない) を使用できます。

pattern = re.compile(
    r"""
        (?<=[[:lower:]])            # preceded by lowercase
        (?=[[:upper:]])             # followed by uppercase
        |                           #   OR
        (?<[[:upper:]])             # preceded by lower
        (?=[[:upper:]][[:lower:]])  # followed by upper then lower
    """,
    re.X,
)

先読み/後読みに依存せずに、2 つの置換パスを使用して、より高度なケースを処理する別の方法:

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

2 つ以上のアンダースコアを含むケースも追加するには:

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

おすすめ記事