본문 바로가기
Language/Python

[Python] 네임스페이스(namespace)에 대한 이해

by 며루치꽃 2021. 12. 8.

네임스페이스(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 값들의 목록을 확인할 수 있다. 

댓글