pep8에 정의된 네이밍 규칙을 알아보겠습니다

(참고: pep8.org/#descriptive-naming-styles)

 

1. _var (_single_leading_underscore)

_single_leading_underscore
: weak “internal use” indicator.

E.g.  from M import *
does not import objects whose name starts with an underscore.

맨 앞에 언더스코어 한개는 변수나 메소드가 "내부용으로만 쓰일 것"이라는 의도를 가진 것입니다.

C++같은 다른 언어들처럼 private으로 만드는 것은 아니고, 프로그래머에게 힌트만 줍니다.

대신 와일드카드 import로 모듈에서 모든 변수, 메소드를 가져올 때 _var는 가져오지 않습니다. (__all__에 넣어서 무시할 수는 있습니다)

와일드카드가 아닌 일반 import는 _var도 가져옵니다. 주의합시다

 

2. var_ (single_trailing_underscore_)

_single_trailing_underscore
: used by convention to avoid conflicts with Python keyword,

e.g.: Tkinter.Toplevel(master, class_='ClassName')

class, def처럼 파이썬 키워드와 겹치는 경우 관례적으로 class_ 이런식으로 사용해 충돌나지 않도록 한다고 합니다.

즉, 키워드와 겹치지 않으면 굳이 var_ 형태로 쓰지 말아야겠죠 헷갈리니까요

 

3. __var (__double_leading_underscore)

__double_leading_underscore
: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo)

위의 1, 2는 인터프리터에서 딱히 해주는게 없습니다. 그런데 맨 앞에 언더바 두개를 붙이면 네임 맹글링(Name mangling)을 수행합니다.

네임 맹글링이라는 것은 이름을 다시 쓰는 것입니다. C++에서는 컴파일러마다 맹글링 규칙이 다른데, MSVC 컴파일러는 void __cdecl TestFunc(char*)이라는 함수 명이 ?TestFunc@@YAXPAD@Z로 변환된다고 하네요.

파이썬은 단순합니다. FooBar라는 클래스 안에 __boo라는 변수가 있으면 _FooBar__boo로 변환합니다.

class Student:
    def __init__(self, name):
        self.__name = name

s1 = Student("vincent")
print(dir(s1))
"""
['_Student__name', '__class__', '__delattr__',
'__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__',
'__lt__', '__module__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__']
"""

클래스 인스턴스에 dir 함수를 사용하면 attribute 목록을 볼 수 있는데, 예제를 보면 Student의 __name 어트리뷰트가 없어지고 _Student__name으로 변환된 걸 확인할 수 있습니다. 따라서 s1.__name으로 접근하면 AttributeError가 발생할 겁니다.

하지만 s1._Student__name으로 접근하는 것은 물론 가능합니다.

역으로 클래스 외부에서 _Student__name = "abc" 이런식으로 __name을 주입할 수도 있다고 하네요. 실제로 그런 형태로 사용할 일은 거의 없겠지만 뭐 그렇다고 합니다.

 

4. __var__ (__double_leading_and_trailing_underscore__, ==dunder)

“magic” objects or attributes that live in user-controlled namespaces.
E.g.  __init__, __import__ or __file__.
Never invent such names; only use them as documented.

3에서 __var의 경우 네임맹글링을 수행한다고 했는데 이름 앞뒤로 언더스코어 두개가 있는 경우(=흔히 던더(dunder, double underscore)라고 부름) 네임 맹글링을 수행하지 않습니다. 즉 이름 그대로 호출할 수 있습니다.

__init__, __repr__ 등 파이썬에서 특수한 용도로 예약된 이름들이 존재하는데, 향후 던더 메소드가 추가되거나 변경될 수 있으니 던더메소드를 직접 만들지 말라고 합니다. (ex. 단일 클래스 내부에서만 사용할 예정이라고해서 __vince__(self, ...) 이렇게 던더로 만들지 말라는 것)

 

+ 추가: _ (single underscore)

언더스코어 하나는 여러 용례가 있습니다

# 1. dummy index
for _ in range(10):
    print("Hi!")

# 2. 'don't care variable' when unpacking
vince = ("Vincent", "Male", "+82-10-1234-1234")
_, _, mobile = vince

먼저 반복문에서 인덱스를 안쓰는 경우, 언더스코어로 이를 명시적으로 표시할 수 있습니다.

튜플 언팩할 때 안 쓸 부분은 don't care로 나타낼 수도 있습니다. C++에서도 비슷하게 std::ignore를 사용할 수 있습니다

>>> 12 + 34
46
>>> _
46
>>> print(_)
46

파이썬 REPL에서 마지막 표현식의 결과값을 나타내는 변수로도 사용할 수 있습니다. 크롬 브라우저에서 $0과 비슷하게 사용할 수 있겠습니다.

from django.utils.translation import ugettext_lazy as _
print(_("Hello!"))  # Will print Hello! if the current language is English
                    # "Bonjour !" in French
                    # ¡Holà! in Spanish, etc.

장고에서 ugettext(or ugettext_lazy)를 사용할 때 보통 _로 리네임해서 씁니다.

반응형