[Python]-class의 self

hannah·2024년 1월 12일
0

Python

목록 보기
3/10

self

파이썬의 기초문법 class를 배우는 도중에 Python에서는 클래스로부터 생성된 각 인스턴스에서 호출할 수 있는 메서드에서 첫 번째 매개변수로 self를 사용해야 한다는 것을 알게 되었다.
JS에서는 매개변수에 이와 같은 것을 안넣어도 동작이 가능했는데 왜 넣어야 하는지가 궁금했다.
구글링을 해보고 GPT에게도 물어본 후, 궁금증이 해소되었다..!

사용이유를 알아보기 전에 self에 대해서 정의해보면,

self는 클래스의 인스턴스 그 자체이다. 다시 말해서, 객체 자기 자신을 참조하는 매개변수이다.

self가 있고 없고의 차이를 코드를 한번 보면,


1. 메서드에 self를 넣지 않은 경우

class Vehicle:
	def car():
    	print('hyundai')
        
ride = Vehicle()
ride.car()

이와 같은 에러메시지가 뜬다!

Exception has occurred: TypeError
Vehicle.car() takes 0 positional arguments but 1 was given
  File "C:\Users\SSAFY\Desktop\markdown\test.py", line 473, in <module>
    ride.car()
TypeError: Vehicle.car() takes 0 positional arguments but 1 was given

이 에러 메시지는 파이썬에서 발생한 TypeError로, 해당 클래스의 car 메서드가 0개의 위치 인자를 받아야 하는데, 실제로는 1개의 위치 인자가 전달되었기 때문에 발생한 것..!

다시 말하면,
Vehicle 클래스 내의 car 메서드는 정의할 때 매개변수로 아무 것도 받지 않아야 한다. 즉, self 매개변수만을 가져야만 한다!

그렇다면 self를 넣으면 어떤 출력값이 나올까?

2. 메서드에 self를 넣은 경우

class Vehicle:
	def car(self):
    	print('hyundai')
        
ride = Vehicle()
ride.car()	# hyundai

이는 self가 인스턴스 메서드 안에서 어떻게 동작하는지 원리를 보면 보다 이해가 쉬울 것이다.

예를 들어, upper 메서드를 사용해 문자열 'hello'를 대문자로 변경해보자

'hello'.upper()

위와 같은 코드는 실제 파이썬 내부 동작이 아래와 같이 이루어진다.

str.upper('hello')

str 클래스가 upper 메서드를 호출했고, 그 첫 번째 인자로 문자열 인스턴스가 들어간다.

따라서 인스턴스 메서드의 첫 번째 매개변수가 반드시 인스턴스 자기 자신이어야 한다.

그렇다면, str.upper('hello')와 같이 적지 않는 이유는?

'hello'.upper()와 같이 단축형 호출 방식으로 즉, 객체 지향 방식의 메서드로 호출해야하기 때문이다.

이때, self는 어디에 위치한 것일까?
객체의 주소를 알려주는 id()함수를 이용해보자.

self id :  2555535419216
hyundai
ride id :  2555535419216

이와 같이 객체의 위치가 동일한 것을 알 수 있다. id가 동일하다는 것은 self와 ride가 동일하다는 것이다!

파이썬의 self를 배우고 난 후, 자바스크립트의 this와 유사한 용도라고 생각했다.

// 자바스크립트에서의 클래스 정의
class MyClass {
  constructor(value) {
    this.value = value;
  }

  printValue() {
    console.log(this.value);
  }
}

const obj = new MyClass(42);
obj.printValue();  // 42

여기서 this는 현재 인스턴스를 가리킨다. this를 사용하여 클래스 내부에서 인스턴스 변수에 접근하여 메서드를 호출할 수 있다.

위와 동일한 코드를 파이썬으로 변환한다면 아래와 같을 것이다.

# 파이썬에서의 클래스 정의
class MyClass {
class MyClass:
    def __init__(self, value):
        self.value = value

    def print_value(self):
        print(self.value)

obj = MyClass(42)
obj.print_value()  # 42

👆 단, Python에서의 self와 JS에서의 this를 완전히 동일시 하면 안된다.

  • self는 명시적으로 지정해주지 않아도 메서드 호출 시 자동으로 현재 인스턴스가 전달된다.
  • this는 메서드를 호출할 때, 직접 전달해주어야 한다.

또한,

  • this는 함수가 호출되는 시점에 동적으로 바인딩된다. 즉, 함수를 어떻게 호출하느냐에 따라 this가 가리키는 대상이 달라질 수 있다는 것을 의미한다.
  • self는 메서드를 호출할 때 인스턴스로 명시적으로 전달되므로 정적으로 바인딩된다.

이러한 차이점도 있으니 아예 같다고 생각하는 것은 금물!


참고로 생성자 메서드(인스턴스 객체가 생성될 때 자동으로 호출되는 메서드)도 마찬가지로 self를 첫번째 인자로 넣어야 한다!

0개의 댓글