• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    해결됨

이런 경우에는 class로 만들어진 객체에 새로운 변수를 외부에서 만들 수 있다고 생각해야 하나요??

21.07.15 21:06 작성 조회수 107

3

질문창에 code sample사용이 익숙치 않아서 사진으로 대체하겠습니다 

위와 같이 Robot class를 정의한 뒤, droid 객체를 만들어 보았습니다.

이후 __age가 아닌 age에 접근해서 값을 변경하는 코드를 작성했는데, 작동을 했고, 기존에 있던 __age가 아닌 새로운 변수 age가 만들어진 뒤, 100으로 초기화가 되는듯 한 현상이 일어났습니다. 

그리고 color라는 class에서는 정의한 적이 없는 변수에 31을 대입해도 잘 작동을 하는것을 확인하였습니다. 

class에서 선언한 적이 없는 변수를 할당한다는것이 선뜻 자연스럽게 받아들여지지 않아서 이런식으로 코드를 짜는 경우가 실제로도 있는지, 이런걸 방지하기 위한(외부에서 새로운 변수를 할당?)방법은 무엇이 있는지 궁금해서 질문 남깁니다! 감사합니다. 

답변 1

답변을 작성해보세요.

5

안녕하세요! 정말 좋은 질문입니다.

파이썬은 C++, Typescript 등 언어와는 다르게 정말 자유롭습니다.

아래의 코드는 C++과 Typescript 코드입니다. 외부에서 color를 만드려니까 아예 불가능한 것을 확인할 수 있습니다.

하지만 Python은 위의 언어와는 다르게 설계되어 있으므로 외부에서 객체의 속성값을 마음대로 추가하고 접근할 수 있죠.

먼저 저희는 캡슐화 기법을 사용하여 언더바 두 개(__)로 내부에서 객체의 속성에 직접 접근할 수 없도록 하였습니다.

간접적으로 안전하게 접근하기 위해 게터(property)와 세터를 사용했죠.

의도에 맞게 __age라면 age에 대한 property를 정의하고 세터를 만드는 것이 일반적입니다.

이렇게 되면 의도에 맞게 안전하게 해당 속성 값인 age를 지킬 수 있죠.

하지만 이현진 님께서 작성해주신 코드처럼 그럴 일은 없겠지만 프로그래머의 실수에 의해 age 대신에

agesss를 property로 정의하게 되었을 경우,

애초에 외부에서 볼 때는 age 자체는 없는 속성이기 때문에,

의도에 맞지 않게 age 속성 값을 새로 정의할 수 있습니다.

또한 color처럼 원치 않은 속성 값도 객체의 네임스페이스(속성)에 추가할 수도 있고요.

이런 현상이 발생하는 이유는 기본적으로 파이썬에서 객체는 __dict__ 에서 속성 값을 관리합니다. (섹션 1 네임스페이스의 이해)

따라서 age를 property로 캡슐화하였다고 해도 애초에 정의하지 않은 droid.color=400, droid.isNice=False 등 외부에서 속성 값을 임의로 추가할 수 있습니다.

(만약 agesss가 아니라 age로 잘 캡슐화하였다면 droid.age을 안전하고 의도에 맞게 접근할 수 있습니다.)

이러한 문제를 해결하기 위해 객체 지향 섹션의 마지막 강의에 나오는 __slots__ 매직 메서드를 사용합니다.

(객체 지향 섹션 마지막 강의 참고하시면 좋을 것 같습니다.)

__slots__ 매직 메서드를 사용하게 된다면, 처음부터 객체의 속성 값을 제한합니다.

아래의 코드처럼 __slots__으로 객체를 __name, __age로 제한한다면 못된 프로그래머가 color 속성을 만드는 것을 막을 수 있습니다.

또한 메모리 절약도 할 수 있죠.

class 안에서 정의한 객체의 속성 값을 외부에서 추가하는 경우는 잘 없습니다.

(별로 좋은 패턴은 아니라고 생각합니다.)

또한 실수가 아니라면 의도에 맞지 않게 다른 이름의 속성 값(agesss)을 property로 정의해서 사용하는 경우도 없습니다.

++

추가적으로 불변 객체로 만들기 위해 __slots__ 매직 메서드로 막는 것 이외에도

아예 객체의 속성을 생성하고 할당하는 매직 메서드인 __setattr( )__을 오버 라이딩해서 막는 방법도 있습니다.

https://docs.python.org/3/reference/datamodel.html#object.__setattr__

도움이 되었나요?

좋은 질문 감사합니다 :)

이현진님의 프로필

이현진

질문자

2021.07.16

친절하고 자세한 답변 정말 감사드립니다. 정말 많은 도움이 되었습니다 ㅎㅎ