Skip to content

Instantly share code, notes, and snippets.

@shoark7
Last active June 22, 2019 04:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shoark7/fb388e6494350442a2d649a154f69a3a to your computer and use it in GitHub Desktop.
Save shoark7/fb388e6494350442a2d649a154f69a3a to your computer and use it in GitHub Desktop.
파이썬에서는 모든 것이 클래스다?

오늘은 클래스에 대해 공부했습니다. 사실 클래스라는 개념이 어렵고 조금은 철학적이기까지 해서 이해가 잘 안 가실 수도 있습니다. 행여나 이해가 당장에 힘드셔도 정말 괜찮은 게 저도 이 개념을 정말 최소한이라도 이해하는 데 1년은 걸린 것 같습니다. 클래스는 일단은 '현실의 실제 개념과 사물(인간, 차, 길거리의 BMW를)을 프로그래밍의 단위로 사용하는 것'이라고 생각하셔도 괜찮을 것 같습니다. 많이 써보다 보면 결국에는 이해하게 됩니다.

여기서는 클래스 또는 OOP(Object-Oriented Programming) 자체보다는 파이썬에서의 클래스의 특징에 대해 말씀드리려고 합니다. 파이썬을 계속 공부하시면 다음과 같은 명제를 들어보실 수도 있습니다. '파이썬에서는 모든 것이 클래스다.' 이게 대관절 무슨 뜻일까요? 일단 저 명제 자체는 '참'(True)입니다. 이 기스트에서는 저 명제가 왜 참인지 대략적으로라도 파악해보겠습니다.


1. 함수 소개: isinstance, issubclass

저 명제를 확인하기 위해 내장 함수 isinstance, issubclass를 사용하겠습니다. 관련 문서(isinstance, issubclass)가 있어서 매우 자세하게 설명하지는 않지만 두 함수는 클래스와 관련한 참/거짓을 판별하는 함수입니다. 한 줄 설명은 다음과 같습니다.

  • isinstance(instance, class) -> instance가 class의 인스턴스 또는 객체 또는 object인지 판단해 True, False 값을 반환
  • issubclass(subclass, superclass) -> subclass가 superclass의 자식 클래스인지, 다시 말해 subclass가 superclass를 상속받는지 판단해 True, False을 반환

이 두 함수를 사용해 정말 파이썬의 모든 것이 클래스인지 살펴보도록 합시다.


2. 파이썬에서 isinstance 사용: 모든 유효한 값은 인스턴스다.

우리가 파이썬을 맨 처음 배울 때 사용했던 값들을 생각해보겠습니다.

print(3, 2.0, False, 'abc', [1, 2, 3], (1,2), {'a', 'b'})

3 2.0 False abc [1, 2, 3] (1, 2) {'b', 'a'}

각각 int, float, bool, str, list, tuple, set 에 속하는 값들입니다.

이때 '파이썬에서 모든 것은 클래스이다'라는 것은 저 값들이 실제로는 자신의 자료형의 인스턴스라는 것을 의미합니다. 3은 int의 인스턴스입니다. int는 이때 클래스가 되고, 무수히 많은 인스턴스를 가질 수 있는데(1, 2, 3, 4, 5, ..., N) 3은 그중 작은 예에 지나지 않습니다.

정말 그런지 'isinstance' 함수를 사용해 확인해보겠습니다.

data_types = [int, float, bool, str, list, tuple, set]
instances = [3, 2.0, False, 'abc', [1, 2, 3], (1,2), {'a', 'b'}]

for inst, cls in zip(instances, data_types):
    print("Is {} an instance of {}?: {}".format(inst, cls, isinstance(inst, cls))) 


Is 3 an instance of <class 'int'>?: True
Is 2.0 an instance of <class 'float'>?: True
Is False an instance of <class 'bool'>?: True
Is abc an instance of <class 'str'>?: True
Is [1, 2, 3] an instance of <class 'list'>?: True
Is (1, 2) an instance of <class 'tuple'>?: True
Is {'b', 'a'} an instance of <class 'set'>?: True

확실히 자료형 자체가 아닌 우리가 사용하는 실제 값들은 자료형의 인스턴스라는 것을 알 수 있습니다.

그러면 같이 따라오는 질문인, '자료형은 클래스라는 뜻인가?'를 issubclass를 사용해 살펴보겠습니다.


3. issubclass 사용: 파이썬에서 모든 데이터 타입은 클래스다.

이전 장에서 isinstance를 통해 값은 자료형의 인스턴스임을 확인했습니다. 그러면 이제는 값이 아닌 자료형이 인스턴스의 모체, 클래스인지 확인해야 합니다. 파이썬에는 수많은 자료형이 있지만 가장 유명하고 많이 쓰이는 것은 앞서 살펴본 int, float, str 등등입니다. 이들이 클래스인지 어떻게 확인할까요?

오늘 영상의 '다중 상속' 파트에서 클래스의 mro라는 함수를 보셨을 것입니다. mro는 'Method Resolution Order'의 약자로, '함수의 결정 순서'라는 뜻을 가지고 있습니다. 지금은 구체적인 의미보다는 mro 함수를 간단하게 사용해보겠습니다.

class A:
    pass
    
class B(A):
    pass
    
class C(B):
    pass
    
print(C.mro())

[__main__.C, __main__.B, __main__.A, object]

이 예제에서 C는 B를 상속받고, B는 A를 상속받습니다. 이때 mro 클래스 메소드는 해당 클래스의 상속 순서를 리스트로 반환하는데요. 왼쪽부터 오른쪽으로 읽어나가면 됩니다. C는 B, B는 A를 상속받는 것을 알 수 있습니다. 그런데 마지막에 object라는 것을 볼 수 있습니다. 그렇다면 A는 object를 상속받는다는 뜻이 됩니다.

이렇게 모든 자료형에(list, str 등등) mro 메소드를 실행해보면 모든 결과의 오른쪽 끝에는 'object'가 자리잡고 있음을 알 수 있습니다. 실제로 파이썬에서는 모든 자료형(내장 자료형, 유저가 만든 커스텀 자료형(A, B 등))이 object라는 원형 자료형의 자식 클래스가 됩니다. 이는 클래스 정의 코드에서 명시적으로 'object'를 상속받지 않아도 내부적으로 설정됩니다.

이를 issubclass를 통해 좀더 직관적으로 살펴보겠습니다. 정말 모든 자료형이 object의 자식 클래스일까요?

data_types = [int, float, bool, str, list, tuple, set]

for tp in data_types:
    print("Is {} a subclass of object?: {}".format(tp, (issubclass(tp, object))))

Is <class 'int'> a subclass of object?: True
Is <class 'float'> a subclass of object?: True
Is <class 'bool'> a subclass of object?: True
Is <class 'str'> a subclass of object?: True
Is <class 'list'> a subclass of object?: True
Is <class 'tuple'> a subclass of object?: True
Is <class 'set'> a subclass of object?: True

매우 대단하게도 우리가 별 생각없이 썼던 자료형들이 실제로 클래스이며, 이들은 모두 파이썬의 원형 클래스 object의 자식 클래스임을 확인할 수 있습니다. 이 정도 확인으로 '파이썬의 모든 것은 클래스다'가 확실히 증명된다고는 생각하지 않습니다만 적어도 저 가설을 지지한다고는 말할 수 있을 것 같습니다. 제가 놓치거나 확실히 하지 않은 맹점은 저도 공부를 해야 좀더 설명이 가능할 것 같습니다.

그래도 확실한 건 '파이썬에서 모든 것은 클래스다'라는 명제는 틀리지 않았습니다.


4. 자잘한 재밌는 팁: int와 bool의 관계

issubclass를 통해 파이썬에서 재밌는 팁을 살펴보겠습니다. 아시는 대로 int는 정수(integer), bool은 참/거짓(boolean)을 나타내는데요. 이 두 자료형(또는 이제는 '클래스'라고 말해도 당당합니다.)에 issubclass 함수를 써보겠습니다.

print(issubclass(int, bool))
print(issubclass(bool, int))

False
True

여기서 알 수 있는 것은 bool은 int의 자식 클래스라는 것입니다. 여기서부터 재미있는 사실을 찾아볼 수 있는데요. 정수에 적용되는 많은 연산들이 bool에도 똑같이 적용됩니다. 자식 클래스는 부모 클래스의 함수나 속성을 오버라이드 하지 않는 부분은 그대로 물려받기 때문입니다.

print(1 == True)
print(0 == False)
print(3 + True)
print(1000000000000000 * False)

True
True
4
0

참, 거짓을 뜻하는 True, False는 사실 1과 0으로 평가됩니다. 그래서 실제 사칙연산에 1과 0을 뜻하는 값에 True와 False을 써도 문제없이 동작합니다.

근데 이것도 참고하셔야 합니다.

print(1 is True)
print(0 is False)

False
False

아까 1은 True, 0은 False와 평가값이 같다고 했는데요.(== 사용시 True) 근데 이들은 실제 메모리상에는 엄연히 다른 위치에 위치하는 다른 객체입니다. 영상에서도 짧게 언급했지만 is 연산자는 각 객체의 메모리 주소값을 비교해 값이 아닌 실제 같은 객체인지 판단해 True/False을 반환합니다. 각각의 예에서 서로는 평가값이 같지만 결국에는 클래스가 다른 엄연히 다른 객체이기 때문에 False가 나올 수밖에 없었습니다.

이 설명을 파이썬 초기에 할까 하다가 너무 잡다해보여서 넘어갔습니다. 마침 클래스에 대해 배우길래 짧게 살펴봤습니다.


쓸데없이 좀 길어졌는데 오늘도 고생 많으셨습니다. 마지막 한 주만 남았는데 모두 소기의 목적을 다 이루시길 바랄게요!
감사합니다. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment