에르노트

파이썬 self (takes 0 positional arguments but 1 was given FIX) 본문

Dev/Python

파이썬 self (takes 0 positional arguments but 1 was given FIX)

두콩 2021. 7. 31. 13:24

파이썬 self

c++ 또는 자바에 'this'라는 키워드가 있다면 파이썬에는 'self'라는 키워드가 있다. 그 뜻은 쉽게 유추가능한대로 '클래스의 인스턴스 자기 자신'이라는 뜻이다. 양쪽 다 실전에서 상당히 빈번하게 사용되는 키워드임은 분명하다. 그런데 c++이나 자바에서는 적어도 this 키워드의 사용을 강제하지는 않는다. 하지만 재밌게도 파이썬에서는 메소드를 정의할 때 self의 사용을 강제하는 것처럼 보인다.

class A:
    def say_a():
        print('a')

a = A()
a.say_a()

 

위의 코드는 다음과 같은 에러 메세지를 남긴다.

TypeError: say_a() takes 0 positional arguments but 1 was given

 

위 에러 문구는 파이썬에서 클래스를 다루다보면 굉장히 쉽게 접할 수 있는 오류이다. 글자 그대로 인자를 요구하지 않는 함수에다가 1개의 인자를 전달해버려서 오류가 났다는 뜻이다. 하지만 위의 예시 코드에서는 분명히 say_a() 라고 호출했기 때문에 인자를 넣지 않았다! 그럼에도 위와 같은 오류가 나는 것은 파이썬 인터프리터가 자동으로 메소드를 호출할 때 인자를 넣어버리기 때문이다.

 

그리고 이 메소드의 첫번째 인자는 어떤 객체에 대해서 데이터를 접근하거나 저장할지를 알려주는 역할을 갖는다. 그래서 위 코드에서 메소드의 파라미터로 'self'를 추가해주면 오류를 없앨 수 있다.

class A:
    def say_a(self):
        print('a')

a = A()
a.say_a()

이렇게 정상적으로 'a'가 출력된다. 그럼 혹시 print('a') 대신에 print(self) 를 넣어주면 어떻게될까?

<__main__.A object at 0x000001E5233ACF10>

첫번째 인자를 통해 해당 객체의 정보를 넘긴다고 했으므로 여기서는 클래스 A를 인스턴스화해서 생성된 객체 a에 대한 정보를 출력한다.


self 는 필수인가?

결론부터 말하자면 그렇지 않다. self는 파이썬에서 키워드이지만 그것의 사용이 강제되지는 않는다는 것이다. 단지 객체 자기 자신을 가리키는 무언가를 지칭할 때 self를 사용하는 것이 하나의 컨벤션일뿐이다.

class A:
    def say_a(this):
        print(this)

a = A()
a.say_a()

단적인 예시로 위와 같이 self 대신에 this를 사용해도 아무 문제가 없다. 코드는 정상적으로 실행되며 self를 사용했을 때와 100% 동일한 결과를 얻을 수 있다. 하지만 파이썬에서는 self를 사용하는 것이 엄연한 관습이므로 다른 개발자와 협업할 일이 있다면 반드시 self를 써주는 것이 좋겠다.


self 를 명시하면 안되는 경우

반대로 메소드를 정의할 때 인자로 self를 명시하면 오류가 발생하는 경우도 있다. 바로 인스턴스화를 거치지 않고 정적 메소드(Static Method) 형태로 사용할 경우이다.

class A:
    def say_a(self):
        print('a')

A.say_a()

 

위와 같이 코드를 작성하면 에러가 난다.

Traceback (most recent call last):
  File "c:\Users\Administrator\Desktop\GUI\selftest.py", line 5, in <module>
    A.say_a()
TypeError: say_a() missing 1 required positional argument: 'self'

 

인스턴스 변수와 클래스 변수가 따로 저장되는 것처럼, 파이썬에서는 클래스를 인스턴스화하지 않고 바로 호출해서 사용할 수 있다. 그리고 이때는 당연하게도 객체를 생성하지 않았으므로 어떤 객체에 대해서 접근할 것인지 파악하는 것이 아무 의미가 없다. 그래서 파이썬 인터프리터는 메소드를 호출할 때는 self에 해당하는 인자를 넘겨주지 않는 것이다.

class A:
    def say_a():
        print('a')

A.say_a()

결국 위와 같이 메소드를 정의할 때 파라미터를 명시하지 않음으로써 에러를 해소할 수 있다.

Comments