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)를 사용할 때 보통 _로 리네임해서 씁니다.
'프로그래밍 > Python' 카테고리의 다른 글
[Python] del과 delattr의 차이점 (0) | 2021.03.25 |
---|---|
[Django] PyCharm으로 장고 커맨드 디버그하는 법 (0) | 2021.03.07 |
[Django] 모델 필드 길이로 필터링하는 법 (0) | 2021.03.02 |
[Django] Proxy model도 마이그레이션이 필요하다 (0) | 2021.02.20 |
[Django] 모델의 clean()이 자동으로 호출되지 않는 이유 (0) | 2021.02.12 |