3-2. Property(UnderScore)

uoayop·2021년 3월 20일
1

Leaf와 Python

목록 보기
11/21
post-thumbnail

다양한 언더 스코어를 활용하면서 접근 지정자에 대해 알아보자.
헷갈렸던 내용이었는데 정리하면서 도움이 꽤 됐다.

Property

  • 오늘의 키워드
    • Python UnderScore(_), 다양한 언더스코어 사용, 접근 지정자 이해

언더스코어가 쓰이는 경우

  • 인터프리터에서 마지막 값을 저장할 때
  • 값을 무시하고 싶을 때
  • 네이밍을 통해 클래스에서 접근 지정자가 달라지도록 하고 싶을 때
  • 국제화, 지역화 함수로 사용하고 싶을 때
  • 숫자 리터럴값의 자릿수 구분을 위한 구분자로써 사용할 때

강의에서는 국제화, 지역화, 자릿수 구분은 다루지 않아서 따로 공부 후 정리해보았다.


1. 인터프리터에서 마지막 값을 저장할 때

  • 파이썬 인터프리터에서 마지막으로 실행된 결과값이 _라는 변수에 저장된다.
>>> 5
5
>>> _
5
>>> _ * 10
50

2. 값을 무시하고 싶을 때

  • 값이 필요하지 않거나 사용되지 않는 값을 _에 할당하면 된다.
# unpacking : 값이 무시가 됨
x, _, y = (1,2,3)
print('ex 1>',x,y)
#packing 처리가 되서 무시가 됨
a, *_, b = (1,2,3,4,5)
print('ex 1>',a,b)
a, *i, b = (1,2,3,4,5) #위의 상황 출력해보기
print(a,i,b)
# for 문에서 변수를 무시할 때도 쓰임
for _ in range(10): 
    pass
for _, val in enumerate(range(10)):
    pass
    # index는 안쓰고 value만 쓰겠다

3. 네이밍을 통해 클래스에서 접근 지정자가 달라지도록 하고 싶을 때

python 접근 지정자

name : public 변수
외부에서 접근 가능하다. 자유롭게 읽기, 쓰기가 허용된다.
_name : protected 변수
상속 관계에서 변수를 나타낼때 사용한다.
__name : private 변수
캡슐화를 통해 내부 처리 과정이 숨겨져있다

  • 클래스 안에 내부 인스턴스를 정의할 때 다음과 같이 지정한다.
    정의한 변수들을 출력을 해보면 차이를 볼 수 있다.
class sample:
    def __init__(self):
        self.x = 0    #public
        self._y = 0   #protected
        self.__z = 0  #private
        
a = sample()       
# public, protected 변수는 출력이 잘 된다.
print('ex 1> x: {}'.format(a.x))
print('ex 1> y: {}'.format(a._y))

# private 변수는 에러 발생
print('ex 2> z: {}'.format(a.__z)) 
# error: AttributeError: 'sample' object has no attribute '__z'
  • dir을 통해 객체 내부를 확인해보자.
print('ex 1>',dir(a))
#[ ... , '_sample__z', '_y', 'x']

⭐️ private 변수는 _(클래스)__(변수 이름) 다음과 같이 이름이 바뀌어서 정의되어 있다.

따라서 아래와 같이 출력과 직접 값 변경이 가능하다. 강제성은 없는 것이다.
그렇지만 약속된 규약이다. rule을 지키자

a._sample__z = 3
print('ex 1> z: {}'.format(a._sample__z))

그럼 private는 어떻게 값 변경을 하나요?

직접 접근하지 말고, Getter, Setter를 통해 값 변경을 해주자.

class SampleB:
    def __init__(self):
        self.x = 0
        self.__y = 0
        # _sampleB__y 로 치환될 것임
    
    def get_y(self): # getter
        return self.__y

    def set_y(self,value): #setter
        self.__y = value

# ⭐️ 이렇게 getter, setter를 만들었지만 여전히 직접 접근해서 변경은 가능하다.

b.x=1
b.set_y(3)
print('ex 2> x={}, y={}'.format(b.x,b.get_y()))

print('ex 2 >',dir(b))
#get_y, set_y가 생겨있다.

파이썬 네임 맹글링 이 공식이 아니라고요?

class sample:
    def __init__(self,value):
        self.__IamPrivate = value
a = sample(1)
#IamPrivate = 1

a._sample__IamPrivate = 3
# 직접 접근해서 수정이 가능하다.

사실 위와 같이 언더스코어 두개를 사용해서 private 변수로 만들어도 직접 접근이 가능하다. 🤯
전세계 개발자들이 언더 스코어 두개로 정의한 변수는 사용하지 않는 암묵적인 규칙을 따르고 있다.
그냥 자율적인 약속을 따르고 있는 격이다.
이를 컨벤션이라고 부른다.

  • 타 클래스에서 언더 스코어 두개로 시작하는 변수는 접근하지 않는 것이 원칙이지만, 사실 변경 가능하다. 그치만.. 그런 짓은 하지말자..
  • 네임 맹글링에 대해 잘 정리된 포스팅이 있어서 공유합니다~ ( 🔗 link )

4. 국제화, 지역화 함수로 사용하고 싶을 때

  • 3번과 같이 어떤 특정한 문법적 규칙이라기보단 컨벤션이다.
    즉, _가 국제화/지역화 함수라는 의미는 아니며, i18n/l10n 함수를 _로 바인딩하는 C 컨벤션에서 유래된 컨벤션이다.

i18/i10 함수는 문자열 번역에 사용할 때 자주 사용됩니다.
국제화와 지역화가 필요한 웹 어플리케이션에서 자주 쓰인다.

특히 Django에서 자주 쓰인다고 한다!

from django.http import HttpResponse
from django.utils.translation import gettext as _

def my_view(request):
    output = _("Welcome to my site.")
    return HttpResponse(output)

#출처: Django Official Document

5. 숫자 리터럴값의 자릿수 구분을 위한 구분자로써 사용할 때

  • Python 3.6에 추가된 문법으로 언더스코어로 숫자값을 좀 더 읽기 쉽도록 자릿수를 구분할 수 있게 되었다.
  • 개발자를 위한 문법이라고 생각하면 되겠다.
# 1000 단위로 표시할때
amount = 10_000_000.0

# 16진수를 단어별로 묶을때
addr = 0xCAFE_F00D

# 2진수를 끊어 읽고 싶을때
flags = 0b_0011_1111_0100_1110

# String 2진수를 변경
flags2 = int('0b_1111_0000', 2)

print(amount)
print(addr)
print(flags)
print(flags2)
print(flags - flags2)


>>> 10000000.0
>>> 3405705229
>>> 16206
>>> 240
>>> 15966

[ 출처 ]
1. 인프런 - 모두를 위한 파이썬 : 필수 문법 배우기 Feat. 오픈소스 패키지 배포 (Inflearn Original)
2. 파이썬 언더스코어(_)에 대하여
3. [Python] 특별한 언더스코어(_)

profile
slow and steady wins the race 🐢

0개의 댓글