Python 정보은닉, __dict__메서드, 캡슐화, pprint

BodeulMaNN·2023년 4월 18일
0

https://goodthings4me.tistory.com/60

파이썬의 객체 외부에서 객체 내에 있는 변수(속성)나 메서드를 수정할 수 없게 하기 위한 코딩 규칙은 attribute, method 앞에 밑줄('_', undercore) 하나를 붙이는 것이다.

  • 100퍼센트 감춰지는 것은 아니다.

그리고, dict 메서드로 변수(속성)정보를 확인하고, 속성값을 수정할 수 있지만, 이를 제한하고 싶을 경우 밑줄  두 개를 붙이는 방법이 있다.

class Simple: 
	def __init__(self, name): 
		self.name = name 
		
	def __str__(self): 
		return '이름은 %s 입니다.' % self.name 
		
	def main(): 
		sp = Simple('Kim') 
		print(sp) 
		sp.__dict__['name'] = 'Park' 
		print(sp) 
		
main()

정보은닉(Information Hiding)

  • 객체(인스턴스) 변수(또는 메소드) 앞에 밑줄( '_', underscore) 한 개를 붙여 private 표현을 한다.

    -참고로, 밑줄 두 개를 붙이면 외부 접근이 불가한 private 효과를 만들 수는 있지만, 실제로 private은 아니다.

    • 이는 Name Mangling(내부적인 어떤 규칙을 통해 함수의 이름을  바꾸는 것)으로 불리는 것으로, 클래스의 확장 시 메서드의 충돌없는 오버라이드를 위해 만들어진 것이라고 한다.
      • 이를 private 효과를 본다고 생각하면 안되며, 일부 오류(부작용)를 초래할 수 있기 때문에 파이썬에서는 객체의 인터페이스 용도(접근 용도)가 아닌 속성(또는 메서드)에는 밑줄(_) 두 개가 아닌 하나를 붙여주는 것이 좋다.
  • 객체 내에 있는 attribute, method 앞에 밑줄 두 개('__' double underscore)를 붙이면 객체 외부에서 해당 이름으로 접근할 수 없게 된다.
  •  attribute, method 앞에 (double underscore)를 붙이면, 해당 이름이 "_Classname속성명 또는 메소드명"으로 변경됨
  • __(double underscore)가 붙은 변수(속성)값 수정하려고 할 경우, 본래 목적이 아닌 해당 객체의 변수로 추가됨

"_이름"

  • 클래스 내부에 언더바 1개(_)가 붙어있는 속성이나 메서드는 private하게 처리된다.

    이는 외부에서 보호된 이름으로 사용되기에 호출해서 사용하면 안된다; 클래스를 사용할 때 내부적으로만 사용할 속성이나 메서드에 붙힌다.

  • "_속성명"은 관행적으로 접근을 보호해야 하므로 별도의 메서드를 구현해서 작성한다.
class Protected:
	def __init__(self, name, age):
		self._set(name, age)

	def _set(self, name, age):
		self._name = name
		self._age = age

	def getname(self):
		return self._name

	def getage(self):
		return self._age

p = Protected('로버트', 30)

print(p.__dict__)

>>> {'_name': '로버트', '_age': 30}

print(p.getname())
print(p.getage())

>>> 로버트
>>> 30

# 다 공개가 되어있기 때문에 속성의 이름을 알면 바로 접근해서 조회할 수 있다.

print(p._name)
print(p._age)

>>> 로버트
>>> 30

mangling

  • "__ + 이름" == 맹글링
  • 맹글링 방식으로 이름을 사용하면 내부적으로 "__클래스__"로 구성된다.
class Mangling:
	def __init__(self, name, age):
		self.__set(name, age)

	def __set(self, name, age):
		self.__name = name
		self.__age = age

	def getname(self):
		return self.__name

	def getage(self):
		return self.__age

p = Mangling('로버트', 31)
print(p.__dict__)

>>> {'_Mangling__name':'로버트', 'Mangling__age':31}

print(p.getname())
print(p.getage())

>>>로버트
>>>31

print(p._name)
print(p._age)

>>>error

Property

  • 프로퍼티를 지정할 땐 주로 데코레이터를 사용한다.
  • 갱신이 필요한 메서드는 "함수명.setter"로 처리한다.
  • 하지만 내부의 속성 이름을 알고 있다면 메서드 대신 속성에 직접 접근해서도 조회나 갱신이 가능하다.
class PropertyClass:
	def __init__(self, name):
		self._name = name

	# 조회
	@property
	def name(self):
		return self._name

	# 갱신
	@name.setter
	def name(self, value):
		self._name = value

p = PropertyClass('설린저')
print(p.name)

>>>설린저
# 조회하면 변경된 것을 확인 가능

p.name = '제라드'
print(p.name)
>>>제라드

print(p.__dict__)
print(p.name)
p._name = '로버트'
print(p.name)
>>> {'_name':'제라드'}
>>> 제라드
>>> 로버트

pprint(): pretty print

>>> import pprint
>>> result = {'userId': 1, 'id': 1, 'title': 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit', 'body': 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'}
>>> pprint.pprint(result)
{'body': 'quia et suscipit\n'
         'suscipit recusandae consequuntur expedita et cum\n'
         'reprehenderit molestiae ut ut quas totam\n'
         'nostrum rerum est autem sunt rem eveniet architecto',
 'id': 1,
 'title': 'sunt aut facere repellat provident occaecati excepturi optio '
          'reprehenderit',
 'userId': 1}

구조가 복잡한 JSON데이터 디버깅 용도로도 사용 가능하다.

참고문헌)
https://goodthings4me.tistory.com/60
https://sikaleo.tistory.com/117

profile
반갑습니다

0개의 댓글