네임스페이스(namespace)에 대한 이해
namespace: 개체를 구분할 수 있는 범위
__dict__ : 네임스페이스를 딕셔너리 형태로 확인할 수 있는 매직 메서드
class Robot:
# 클래스 변수: 인스턴스들이 공유하는 변수
population = 0
# 생성자 함수
def __init__(self, name, code): #self는 각각의 인스턴스
self.name = name # 인스턴스 변수
self.code = code
Robot.population += 1
# 인스턴스 메서드
def say_hi(self):
print(f"Grettings, my masters call me {self.name}.")
# 인스턴스 메서드
def cal_add(self, a, b):
return a + b
# 인스턴스 메서드
def die(self):
print(f"{self.name} is being destoryed")
@classmethod
def how_many(cls):
print(f"we have {cls.population} robots")
클래스가 위와 같이 정의되어 있다고 하고 아래와 같이 클래스의 __dict__을 프린트 해보자
print(Robot.__dict__)
>>>
{'__module__': '__main__', 'population': 3, '__init__': <function Robot.__init__ at 0x0000025FFD83C0D0>, 'say_hi': <function Robot.say_hi at 0x0000025FFD83C160>,
'cal_add': <function Robot.cal_add at 0x0000025FFD83C1F0>, 'die': <function Robot.die at 0x0000025FFD83C280>,
'how_many': <classmethod object at 0x0000025FFD7C0F40>, '__dict__': <attribute '__dict__' of 'Robot' objects>,
'__weakref__': <attribute '__weakref__' of 'Robot' objects>, '__doc__': None}
프린트를 해보면 클래스 변수로 선언한 population, how_many 클래스 메서드도 존재하는 것을 확인할 수 있다. 그런데, __module__ 도 있고, __doc__ 도 있고 인스턴스 메서드로 선언한 say_hi, cal_add, die 가 클래스 네임스페이스 공간 안에 들어가 있다. 왜 네임스페이스 공간 안에 들어가 있는 것일까?
siri = Robot("siri", 123)
print(siri.__dict__)
>>> {'name': 'siri', 'code': 123}
다음과 같이 인스턴스가 선언되어 있다고 가정하고 siri의 __dict__ 를 print해보면 name, code 의 인스턴스 변수를 확인할 수 있다. 하지만, 해당 공간에 인스턴스 메서드로 선언한 say_hi, cal_add, die를 확인할 수 없다.
이유는 함수를 정의할 때, 함수를 대입하는 케이스는 많이 없다. 그래서 파이썬은 메모리 효율을 위해서 클래스 네임스페이스에 인스턴스 메서드를 저장한걸로 생각하면 된다.
siri.cal_add(2, 3)
그렇다면 인스턴스 네임스페이스에 없는 cal_add()는 어떻게 호출되는 것일까?
파이썬 내부적으로 인스턴스 네임스페이스인 siri에 없다면 상위 클래스인 Robot으로 가서 해당하는 변수와 메서드를 찾기 때문이다.
print(siri.population)
>>> 5
print(siri.how_many())
>>> we have 1 robots
이 원리를 이용하여 인스턴스를 이용하여 siri.population을 프린트해본다면 클래스 변수인 population을 확인할 수 있다. 이와 같은 원리로 인스턴스를 이용하여 클래스 메서드인 how_many를 확인할 수 있다.
그렇다면, Robot 클래스 안에 say_hi() 라는 인스턴스 메서드로 정의했는데
Robot.say_hi() # 에러
>>> TypeError: say_hi() missing 1 required positional argument: 'self'
다음과 같이 클래스에 say_hi()라는 메서드를 호출하면 어떤 결과가 이뤄질까?
그러면 다음과 같은 TypeError가 뜨는 것을 확인할 수 있는데 self에 인자가 없어서 사용할 수 없다. 이를 통해 인스턴스 메소드임을 알 수 있게 된다.
Robot.say_hi(siri)
siri.say_hi()
이를 해결하려면 위와 같이 인스턴스를 넣게 된다면 아래에 있는 인스턴스 메서드를 직접호출하는 결과와 같은 결과를 얻을 수 있다. 첫번째 줄은 Robot 안의 네임스페이스 안에 있는 say_hi라는 메서드를 찾아서 실행을 하는데 이것은 인스턴스 메서드이기 때문에 인스턴스 인자로 인스턴스를 전달해주면 된다.
두번째 줄은 say_hi()가 인스턴스 메서드이기 때문에 siri로 접근할 수 있도록 하는 것이다.
dir()
네임스페이스를 사용자화 하여 네임스페이스의 key 값을 확인할 수 있는 built-in 메서드이다.
print(dir(siri))
>>>
['__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__', 'cal_add', 'code',
'die', 'how_many', 'name', 'population', 'say_hi']
dir( ) 을 프린트 해본다면 인스턴스 siri를 통해 접근할 수 있는 key 값들의 목록을 확인할 수 있다.
'Language > Python' 카테고리의 다른 글
[Python] 컴포지션(composition) (0) | 2021.12.16 |
---|---|
[Python] 캡슐화(encapsulation) - @property 와 getter와 setter의 개념 (0) | 2021.12.14 |
[Python] 제네레이터(Generator)를 이용한 itertools 예시 (0) | 2021.12.01 |
[Python] 반복자(Iterator), 제너레이터(Generator)에 대한 이해 (0) | 2021.11.24 |
[Python] 데코레이터(Decorator) (0) | 2021.11.17 |
댓글