프로그래밍/Python

[Python] class의 재미난 특징

채윤아빠 2022. 5. 12. 07:14
728x90
반응형


파이썬 클래스를 이용하면서 몇 가지 재미난 특징이 있어서 정리해 둡니다.

클래스의 동적 정의

첫 번째는 선언된 클래스라도 중간에 동적으로 멤버 변수 및 멤버 함수를 추가할 수 있다는 점입니다.

뭐 당연한 것인데, 여기에 "isinstance()" 함수가 연관되면 재밌게 됩니다.

아래 예제를 보시면, 특정 클래스에 멤버 변수를 동적으로 추가하는 하였습니다. 멤버 변수를 추가하기 전과 추가한 후의 "isinstance()" 함수의 반환값이 어떻게 될지 추측해 보시기 바랍니다.

class MyClass:
    def __init__(self):
        self.data = 5

b = MyClass()
print(f'isinstance(b, MyClass) is {isinstance(b, MyClass)}')
print(b.__dict__)
b.data2 = 100
print(b.__dict__)
print(f'isinstance(b, MyClass) is {isinstance(b, MyClass)}')

자유도를 보장하기 위해서인지는 모르겠지만, 결과는 "같다" 입니다. 동적으로 멤버 변수 및 함수가 추가되어도 본질은 같다는 점을 잘 활용하면 다중 상속 등을 하지 않고도 활용할 수 있는 곳이 꾀 될 것 같습니다.

위 예제의 실행 결과는 다음과 같습니다.

isinstance(b, MyClass) is True
{'data': 5}
{'data': 5, 'data2': 100}
isinstance(b, MyClass) is True

private 멤버 변수

파이썬에서 클래스의 private 멤버 변수를 선언하기 위해서는 변수명 앞에 "__"를 붙이도록 되어 있습니다.

class MyClass:
    def __init__(self):
        self.__data = 5

위와 같이 "__data" private 변수를 선언 후, 외부에서 사용하려고 하면 다음과 같은 오류가 발생합니다.

>>> c = MyClass()
>>> c.__data
Traceback (most recent call last):
  File "<pyshell#61>", line 1, in 
    c.__data
AttributeError: 'MyClass' object has no attribute '__data'

이 때, c 객체의 모든 변수를 출력해 보면 다음과 같습니다.

>>> c.__dict__
{'_MyClass__data': 5}

해당 클래스의 private 변수라고 하더라도 "_<클래스명><private 변수명>"으로 하면 접근이 가능합니다.

>>> c._MyClass__data
5
>>> c.__dict__['_MyClass__data']
5

이는 상속 관계에서도 동일하게 적용됩니다.

class MyClass:
    def __init__(self):
        self.__data = 5
        self.data = 1

class MySubClass(MyClass):
    def __init__(self):
        super().__init__()
        self.__data = 10

d = MySubClass()
print(d.__dict__)
# {'_MyClass__data': 5, 'data': 1, '_MySubClass__data': 10}

부모 클래스와 자식 클래스에서 동일한 "__data" private 멤버 번수를 선언하면 위와 같이 각각 할당이 되고, 외부에서는 "_<클래스명><private 변수명>"으로 각각 접근이 가능합니다.

>>> d._MyClass__data
5
>>> d._MySubClass__data
10

참고자료