Python의 Code는 PEP-8에 의거하여 작성하는 것을 권장하고 Snake_case를 기반으로 표기를 하는데 Python 내에서도 Underbar(_)는 다양한 용도로 사용한다.
다음은 용도에 대하여 분류하였다.
1. Interpreter의 마지막 값의 대용으로 사용
Python에서 연산을 마쳤을 때 Underbar는 Interpreter에서 마지막으로 출력한 값으로 사용할 수 있다.
python3
>>> 1+1
2
>>> _+1
3
>>> _*3
9
2. 버리는 값
Python에서 Code를 입력할 때 버리는 값으로 Underbar를 많이 사용한다. 하지만 기능적으로 의미가 있는 것은 아니고 버리는 값이라고 명시적으로 표기해 주는 것이다.
Example :
one = "*"
two = "**"
for _ in range(3):
print(one)
print(two)
Result :
*
**
*
**
*
**
3. 숫자 자릿수 표현
Python에서는 기본적으로 정수를 바인딩할 때 다음과 같이 표현한다.
number = 123456789
하지만 여기서 Underbar를 이용해서 숫자 자릿수를 나누어줄 수 있다.
number = 123_456_789
결과 값은 동일하다.
Example :
number = 123456789
number_ = 123_456_789
print(number)
print(number_)
Result :
123456789
123456789
4. 객체의 사용처를 구분할 때
해당 Case에는 4가지로 볼 수 있는데 앞에 1개, 뒤에 1개, 앞에 2개 앞 뒤로 2개씩 붙은 총 4개의 Case가 있다.
1) _case (Underbar가 앞에 1개)
첫 번째 케이스로 _가 이름 앞에 붙어있을 때는 해당 모듈 내에서만 객체를 사용하겠다는 의미를 지니고 있다.
# Python file with some functions
# plus_minus.py
def _plus(a,b):
return a+b
def minus(a,b):
return a-b
plus_minus.py라는 파일을 만들고 main.py 에서 import를 하여 사용하는 상황을 가정을 해보았을 때
Example :
# main.py
from plus_minus import _plus
print(_plus(1,2))
Result :
3
위의 경우는 특정 함수를 가져온다고 명시하여 주었기 때문에 에러가 없다.
하지만 특정 함수를 지정하여 import를 해주는 것이 아니라면 에러를 발생한다.
Example :
# main.py
from plus_minus import *
print(_plus(1,2))
Result :
NameError: name '_plus' is not defined
minus의 함수는 잘 작동한다.
Example :
# main.py
from plus_minus import *
print(minus(1,2))
Result :
-1
2) case_(Underbar가 뒤에 1개)
이번 케이스는 기능적으로 특별한 의미가 있지는 않으나 변수를 지정하거나 함수를 선언할 때 Python 내 자체 함수들과 충돌을 방지하고자 할 때 사용한다.
Example :
int = 3
print(int)
Result :
3
결과는 3으로 Terminal에서 반환하지만 int의 함수를 덧씌움으로 해당 Python 내장 함수를 사용하지 못한다.
그렇기에 int_와 같은 표기 방식으로 충돌을 방지하고자 이름 뒤에 Underbar를 이용한다.
3) __case(Underbar가 앞에 2개)
이름 앞에 Underbar가 2개 붙여서 사용하는 것을 'name mangling'이라고 하며 특수한 기능을 가지고 있다.
Python은 class를 선언할 때 다른 언어처럼 Public/Protected/Private 같은 class의 Field를 지정하지 않고 전부 Public으로 사용한다.
그렇기에 name mangling으로 Private와 유사하게 접근을 제한하거나 상위 class의 Overriding을 방지할 수 있다.
아래는 일반적으로 class 선언 후 속성을 출력한 것이다.
Example :
class Apple:
def __init__(self):
self.pc = "imac"
self.mobile = "iphone"
self.watch = "apple-watch"
test = Apple()
print(test.pc)
print(test.mobile)
print(test.watch)
Result :
imac
iphone
apple-watch
하지만 name mangling을 이용하면 다른 결과를 보인다.
Example :
class Apple:
def __init__(self):
self.pc = "imac"
self.mobile = "iphone"
self.__watch = "apple-watch"
test = Apple()
print(test.pc)
print(test.mobile)
print(test.__watch)
Result :
imac
iphone
Traceback (most recent call last):
File "/Users/user/Desktop/main.py", line 10, in <module>
print(test.__watch)
AttributeError: 'Apple' object has no attribute '__watch'
다음과 같이 name mangling을 이용한 곳만 AttributeError를 나타내는 것을 볼 수 있다.
그러면 '어떻게 해당 속성에 접근이 가능한가?'라는 의문이 있을 수 있는데 다음과 같이 확인할 수 있다.
Example :
class Apple:
def __init__(self):
self.pc = "imac"
self.mobile = "iphone"
self.__watch = "apple-watch"
test = Apple()
print(dir(test))
Result :
['_Apple__watch', '__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__', 'mobile', 'pc']
첫 번째로 있는 속성은 '_Apple__watch'이고 이는 name mangling으로 만들어진 속성을 의미하며 해당 명칭으로 접근을 해야 속성을 불러올 수 있다.
Example :
class Apple:
def __init__(self):
self.pc = "imac"
self.mobile = "iphone"
self.__watch = "apple-watch"
test = Apple()
print(test._Apple__watch)
Result :
apple-watch
4) __case__ (Underbar가 앞 뒤로 2개씩)
해당 case는 Python을 접한 사람들은 어느 정도 보았을 것이다.
ex ) __init__ (생성자)와 __del__ (소멸자)와 같은 case
Underbar를 앞 뒤로 2개씩 붙여서 사용하는 경우는 Python에 자체적으로 정의한 변수 또는 함수라는 표기이다.
Python내 자체 변수/ 함수들을 보면(ex. 이전 case에서 class 내부를 보았을 때) 앞 뒤로 표기되어 있는 Underbar가 2개씩 있는 것을 확인할 수 있다.
Example :
class Apple:
def __init__(self):
self.pc = "imac"
self.mobile = "iphone"
self.__watch = "apple-watch"
test = Apple()
print(dir(test))
Result :
['_Apple__watch', '__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__', 'mobile', 'pc']
(Python 자체함수 dir(object)를 이용하여 확인 가능)
별도의 특수한 기능있는 것이 아니고 Python내에서 합의하여 사용하고 있는 사항이며 Python내 함수/변수를 Overriding하여 사용하는 경우나 기존의 함수/변수를 호출하여 사용하는 경우를 제외하고는 일반적으로 사용할 일이 없다.
'Programming > Python' 카테고리의 다른 글
[Python] 생성자(__init__)와 소멸자(__del__) (0) | 2022.10.21 |
---|---|
[Python] GIL(Global Interpreter Lock) (3) | 2022.10.15 |
[Python] 파이썬이란 (0) | 2022.10.13 |