클래스 객체와 인스턴스 객체의 이름공간
-
코드 작성 시 주로 발생하는 실수 중 하나가
클래스 메서드 내에서 인스턴스(self)를 통하지 않고 변수에 접근하는 것이다.
-
전역 영역의 변수와 클래스의 변수의 이름이 동일한 경우
에러도 발생하지 않기 때문에 규모가 큰 프로그램에서는 이런 문제를 찾기가 쉽지 않다.
>>> str = "NOT Class Member"
>>> class GString:
... str=""
... def Set(self,msg):
... self.str = msg
... def Print(self):
... print(str) # self를 이용해 클래스 멤버에 적브하지 않는 경우
# 이름이 동일한 전역 변수에 접근해서 출력함
>>> g = GString()
>>> g.Set("First Message")
>>> g.Print()
NOT Class Member
>>> class GString:
... str=""
... def Set(self,msg):
... self.str = msg
... def Print(self):
... print(self.str)
>>> g = GString()
>>> g.Set("First Message")
>>> g.Print()
First Message
-
위 예제에서는 전역 영역과 클래스 영역에 동일한 이름인 str이라는 변수가 존재한다.
-
변수 이름이 같아도 다른 영역에 존재하기 때문에 당장은 문제가 되지 않는다.
하지만 멤버 메서드인 Print() 내부에서 개발자의 실수로
인스턴스 객체 self를 통하지 않고 전역 변수 str 값을 출력하고 있다.
-
그렇기 때문에 의도와는 다르게 출력 결과는 전역 변수 str값이 출력된다.
-
인스턴스 객체가 자신을 생성한 클래스 객체를 참조하기 위해
파이썬에서는 인스턴스 객체의 내장 속성 ‘class‘가 있다.
-
클래스 영역에 모든 인스턴스 객체에 공통된 데이터를 참조하기 위해 아래와 같이 사용한다.
>>> class Test:
... data = "Ki yong"
>>> i2 = Test()
>>> i1 = Test()
>>> i1.__class__.data = " Good Gid " # "__class__" 속성을 이용해 클래스 데이터를 변경
>>> print(i1.data) # 참조하는 모든 인스턴스가 변경
Good Gid
>>> print(i2.data)
Good Gid
>>> i2.data = " Local Change " # i2 인스턴스 객체의 데이터만 변경
>>> print(i1.data)
Good Gid
>>> print(i2.data)
Local Change
>>> print(i2.__class__.data) # i2의 클래스 객체의 데이터는 변경되지 않음
Good Gid
-
인스턴스 객체 ‘i2’의 이름공간에 멤버 변수 ‘data’를 변경하는 경우
우선적으로 인스턴스 이름공간을 탐색하기 때문에 인스턴스 이름공간의 데이터를 출력한다.
-
물론 인스턴스 객체에 동일 이름의 데이터가 존재하더라도
__class__
를 이용해 클래스 이름공간의 데이터에 접근할 수 있다.