본문 바로가기

Python_programming

Python 생성자(__new__)에 대한 고찰

"클래스 속성과 메서드"는 예전에 다른 포스팅에서 잠시 다룬적 있지만 이번에는 "생성자"에 포커스를 맞춰서 정리해보겠습니다.

 

파이썬에서 클래스 만들 때, self 라고 하는 "인스턴스화 될때의 레퍼런스"를 갖고 있는 매개변수를 넣어줍니다. 

그런데, "self 고찰"포스팅 마지막 부분에 self 를 꼭 넣어줘서 인스턴스 메서드나 속성에 접근하는거 이외에 클래스 자체에도 접근할 수 있게끔 클래스 속성이나 클래스 메서드도 있다라고 얘기를 했습니다. 

 

이 때, 생성자라는 개념을 알아야 하는데요. 생성자는 정적 메서드(static method)이고 첫 번째 매개변수는 cls , 즉 클래스 객체를 받아서 처리합니다. 생성자는 아무 것도 하지 않는 인스턴스 객체를 생성만 합니다. 인스턴스 내의 속성은 초기화에서 처리하기를 권고합니다. 하지만 특별한 처리가 필요할 경우 추가로 생성자를 재정의해서 사용해야합니다.

 

아래 예시를 보겠습니다.

생성자는 new라는 이름의 스폐셜 메서드입니다. " __new__  "

해당 메서드의 첫 번째 인자는 self 가 아닌 cls 입니다. 이럴 경우 생성자에서 return 값이 무엇이느냐에 따라 새로운 인스턴스가 만들어질 수 있고, 기존 클래스의 레퍼런스를 return 할 수 있습니다.(=새 인스턴스 안 만들어짐)

 

 

# AAA 라는 클래스 생성자로 새로운 인스턴스 만들기

aaa = AAA() 

 

 

 

 

 

자, 클래스 생성자로 인스턴스를 만들었는데 이는 self 객체를 이용해서 만드는 것과는 좀 다르다.  self 객체를 사용하는 초기화  __init__  는 좀 더 하위의 인스턴스를 의미합니다. 일종의 자식같은? 느낌입니다.

 

하지만, cls 로 만든 건 클래스 자체로 아무것도 하지 않는 생성자를 만듭니다. 조금 더 커스터마이징을 많이할 수 있는? 그러한 객체를 만들기 위해 사용하는 것 같습니다.

 

즉, 클래스에서 특정한 로직이 필요한 경우는 생성자인 __new__ 메서드를 재정의해서  인스턴스 객체를 만들면  다양한 기능을 추가할 수 있고 초기화도 생성자에서 처리할 수 있기 때문입니다. 

 

 

 

 

 

 

 

자, 이번에는 새로운 인스턴스를 만들지 않고 자기 자신을 반환하도록 만들어보자.

(무엇이 달라졌는지 클래스 정의부분을 앞에 거랑 비교해서 보길!)

 

 

 

 

 

 

 

return 문이 조금 다르다. 앞에 번에는 return object.__new__(cls) 이고, 방금은 return cls 이다. 

이 차이점은 인스턴스를 생성해보면 알 수 있다.

레퍼런스가 동일하게 나온다. ok 와 OnlyKlass 의 레퍼런스는 동일하다.

이것은 실질적으로 인스턴스가 만들어진 것이 아니다.

 

생성자를 재정의하는데 있어서의 차이점은 "무엇"을 반환했는지 여부이다. 

최상위 클래스인 object 생성자로 기존 cls 를 반환해버리면 새로운 인스턴스가 만들어지고...

(=동일하지 않은 레퍼런스 발생 => 새로운 객체 생성)

 

메서드 사용하지 않고 그냥 cls 자체, 클래스 자체를 반환해버리면 새로운 인스턴스가 만들어지지 않는다.(동일 레퍼런스 발생)

 

자, 그러면 자기 클래스만 반환해서 인스턴스 생성을 막는 위 클래스에 메서드를 만들면? 

 

클래스 메서드이다.

클래스 메서드를 만드는 것은 메서드 위에 @classmethod 를 정의해주면 된다.

아래 코드를 보자.

 

 

 

 

 

 

네임스페이스를 보면 만들어진 메서드는 클래스 메서드라고 나온다. 그리고 생성자는 staticmethod 라고 나온다.

 

 

 

 

 

클래스로 인스턴스를 생성하면 자기 자신의 레퍼런스를 반환하므로 클래스이고 클래스 메서드를 가지고 클래스 속성을 갱신한 뒤 이를 조회하면 갱신된 결과를 출력하는 것을 확인할 수 있다. 

 

자, 이 방법은 클래스를 하나의 객체처럼 사용할 수 있는 방법이다. 인스턴스를 생성하지 않았고, (그렇게 보이지만 레퍼런스 새로운 거 안나왔으니깐!) 하나의 객체처럼 클래스를 사용할 수 있다.

 

 

 

 

 

### 참고 서적 ### 

 

위 포스팅은 BJ퍼블릭 출판사의 문용준 선생님의 '한 손 파이썬' 책을 토대로 정리한 내용입니다 :)

 

### 참고 블로그 ##

 

wikidocs.net/16071

 

위키독스

온라인 책을 제작 공유하는 플랫폼 서비스

wikidocs.net

stackoverflow.com/questions/6578487/init-as-a-constructor

 

__init__ as a constructor?

Dive into Python - It would be tempting but incorrect to call this the constructor of the class. It's tempting, because it looks like a constructor (by convention, __init__ is the first ...

stackoverflow.com