클래스의 기본적인 생성 방법은 아래 링크의 글을 참고하면 좋을 것 같다.
https://reo91004.tistory.com/216
클래스와 인스턴스의 차이를 명확히 하자
정보를 찾다 보면 객체와 인스턴스를 자주 언급된다. 둘이 같은 것이라고 하는데, 정확한 차이를 알아보자.
우선 클래스로 만든 객체를 인스턴스라고 한다. 이렇게 말하면 같은 게 맞지 않나 생각이 든다.
Klass 클래스를 활용해 kls = Klass() 로 만든 객체는 kls다. 즉 kls는 객체이다.
또한 kls 객체는 Klass의 인스턴스이다.
즉 인스턴스와 객체라는 말은 어떠한 관계라는 면에서 어감이 좀 다르다. 아래 예를 보자.
kls는 인스턴스이다. 보다는
kls는 객체이다. 가 적절하다.
kls는 Klass의 객체이다. 보다는
kls는 Klass의 인스턴스이다. 가 적절하다.
결론은 둘이 의미상 같은 것이 맞지만 주술 관계에 따라 선택하는 것이 좋다.
__init__과 __new__의 차이
둘의 차이점에 대해 찾다 보면 자세하게 기술되어 있는 것 같으면서도 너무 두루뭉술해서 직접 정리해본다.
__init__은 인스턴스 초기화에 사용하는 특수 메서드다. 인스터스 초기화에 대해 짚고 넘어가보자.
인스턴스 초기화라 하면 C++나 Java 등의 생성자(Constructor)를 떠올리는 사람이 많을 수 있다. C++, Java에서는 실제로 생성자가 인스턴스 생성과 초기화 둘 다 수행하기 때문이다. 그러나 파이썬의 __init__은 인스턴스 생성 후 호출된다는 점에서 생성자와 다르다.
즉 C++/Java의 생성자는 인스턴스 생성/초기화를 수행하고, 파이썬의 __init__은 인스턴스 초기화를 수행한다.
파이썬에서 생성자에 대응하는 메서드를 찾는다면 __new__를 들 수 있다. 반환값은 해당 클래스의 인스턴스가 된다.
이는 클래스 객체를 호출해 인스턴스화를 수행할 때 __new__를 호출한 후 그 반환값을 __init__의 첫 번째 인자인 self로 반환한다고 말할 수 있다. 유의할 점은 인스턴스를 반환하지 않는다면 인스턴스화가 되지 않는다. 아래에서 다시 다룬다.
__new__는 클래스 자기 자신을 인자로 받는다. 주로 cls라고 선언한다.
class Klass:
def __new__(cls, *args): # *args로 여러 인자를 받음
print('cls :', cls) # cls 정보 출력
print('new :', args)
return super().__new__(cls) # Klass 인스턴스 반환
def __init__(self, *args): *args로 여러 인자를 받음
print('init :', args)
kls = Klass(1, 2, 3)
>>>
cls : <class '__main__.Klass'>
new : (1, 2, 3)
init : (1, 2, 3)
유의할 점은 super().__new__(cls)이다. 위에서 말했듯 해당 클래스의 인스턴스를 반환해야 하므로 부모 클래스에서 __new__를 호출하는데 자신을 인자로 주어 해당 값을 반환한다.
__new__ 사용 시 주의할 점?
사실 __new__를 사용할 일이 별로 없다. 대부분의 인스턴스 초기화는 __init__으로 해결되기 때문이다.
그러나 __new__를 활용하면 일반적인 상황에서는 할 수 없는 동작을 간단히 구현할 수 있다. 아래 코드를 보자.
class Person:
def __new__(cls, name):
if isinstance(name, str): # name을 문자열로 받았다면
return super().__new__(cls) # 이 객체의 인스턴스 반환
else:
print("문자열로 받지 않았습니다.")
return -1
def __init__(self, name):
self.name = name
print(Person(1004))
print(Person('Reo').name)
>>>
문자열로 받지 않았습니다.
-1
Reo
사람의 이름을 문자열로 받지 않았을 때 아예 객체를 반환하지 않도록 해 Person 인스턴스가 되지 않는 식으로 사용할 수 있다. 그런데 사실 __new__ 메서드 자체를 잘 사용할 일이 없는 것으로 알고 있다.
print(Person(1004).name)
>>>
문자열로 받지 않았습니다.
Traceback (most recent call last):
File "C:\Users\reo91\OneDrive\Coding Practice\P C++, Python\Python2.py", line 12, in <module>
print(Person(1004).name)
AttributeError: 'int' object has no attribute 'name'
위에서 언급했던 것처럼 Person의 인스턴스화가 진행되지 않았고, -1을 반환했기 때문에 int 객체가 name을 가지지 않는다는 오류가 나온다.
'◎ Python > 알게된 것 정리' 카테고리의 다른 글
[Python 정리] if __name__ == "__main__": 의 의미, 활용법 (2) | 2022.09.24 |
---|---|
[Python 정리] 프로퍼티, setter, 프라이빗 속성이란? (0) | 2022.09.24 |
[Python 정리] 파이썬에서의 데이터 구조 (0) | 2022.09.22 |
[Python 정리] 파이썬 all/any 함수 (0) | 2022.09.21 |
[Python 정리] 독스트링, python/python3, 빈 리스트 판별, 동적/정적 언어 (0) | 2022.09.15 |
자기계발 블로그