HOWTO · Python
Python TypeError: 필수 위치 인수 1개 누락
이 튜토리얼에서는 TypeError: missing 1 required positional argument: self in Python에 대해 설명합니다.
이 페이지의 내용
TypeError: missing 1 required positional argument: 'self'는 보통 인스턴스 없이 인스턴스 메서드를 호출했다는 뜻입니다. def fun(self)과 같은 메서드에서 self는 관례상 첫 번째 매개변수이며, 메서드를 객체를 통해 호출하면 Python이 이 자리에 해당 객체를 전달합니다. self는 속성이 아니라 매개변수입니다. class 자체는 인스턴스가 아니므로, 먼저 객체를 만든 다음 그 객체에서 메서드를 호출하세요.
“missing 1 required positional argument: ‘self’”의 의미
데코레이터 없이 클래스 안에 정의한 함수는 인스턴스 메서드입니다. 인스턴스를 통해 메서드에 접근하면 Python은 해당 인스턴스를 메서드에 바인딩해 self로 전달합니다. 같은 메서드에 클래스에서 직접 접근하면 바인딩할 인스턴스가 없으므로 첫 번째 필수 매개변수가 채워지지 않습니다.
오류 문구는 메서드의 주 작업에 필요한 값이 빠졌다는 뜻이라기보다, 어떤 매개변수가 누락됐는지를 나타냅니다. 메서드가 def greet(self, name)으로 선언된 경우, name을 전달했더라도 인스턴스에 바인딩하지 않고 호출하면 self가 누락될 수 있습니다. 호출 인수가 맞지 않아 발생하는 TypeError입니다.
클래스에서 인스턴스 메서드를 호출하면 오류가 발생하는 이유
Delft.fun()은 Python에 클래스에서 함수를 호출하라고 요청합니다. fun이 self를 요구한다면 인스턴스를 명시적으로 전달하거나, 더 명확하게는 인스턴스에서 메서드를 호출해야 합니다. 클래스 자체를 변수에 할당하는 것도 흔한 실수입니다. m = Delft는 객체를 만들지 않습니다. 따라서 m.fun()도 여전히 클래스에서 메서드에 접근하므로 self가 바인딩되지 않습니다.
생성자에 데이터가 필요하다면 Delft("Stack")처럼 객체를 만드는 호출에 그 데이터를 전달해야 합니다. 생성자 호출에서 괄호를 생략하면 인스턴스가 만들어지지 않으며, self에 값이 전달되는 것도 아닙니다. 클래스는 클래스 자체로 호출할 수 있고, 클래스에서 메서드에 접근하는 방식이 본질적으로 잘못된 것도 아닙니다. 호출에 메서드의 매개변수와 맞는 인수를 전달해야 합니다.
인스턴스를 만들어 호출 수정하기
필요한 생성자 인수를 전달해 인스턴스를 만들고 변수에 저장한 다음, 그 인스턴스에서 메서드를 호출하세요. 다음은 일반적인 호출 방식을 보여 주는 독립적인 예제입니다.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
class Delft:
def __init__(self, name):
self.name = name
def fun(self):
return self.name
m = Delft("Stack")
print(m.fun())
이 예제는 정상적으로 실행되어 Stack을 출력합니다. 호출할 때 m이 self에 바인딩되고, 메서드는 인스턴스를 만들 때 저장한 이름을 반환합니다.
정적 메서드가 적합한 경우
정적 메서드에는 인스턴스가 자동으로 전달되지 않습니다. 어떤 작업이 개념상 클래스에 속하지만 인스턴스 상태를 읽거나 변경하지 않는다면 @staticmethod를 사용하세요. 예를 들어 클래스에서 명시적으로 전달받은 인수만 사용하는 형식 지정 도우미를 제공할 수 있습니다. API에 맞게 클래스나 인스턴스에서 이 도우미를 호출하면 됩니다.
인스턴스 메서드를 정적 메서드로 바꾸는 것이 이 TypeError를 해결하는 일반적인 방법은 아닙니다. 작업에서 self.name이나 그 밖의 객체별 데이터를 사용한다면 인스턴스 메서드로 유지하고 객체를 만드세요. 반대로 self 매개변수를 사용하지 않는다면 이를 제거하고 @staticmethod를 추가해 의도한 호출 방식을 명확히 할 수 있습니다.
메서드 정의와 호출 위치 확인하기
메서드 시그니처를 읽고 각 필수 매개변수에 맞는 인수가 호출에 전달되는지 확인하세요. 첫 번째 매개변수가 self라면 괄호를 사용해 만든 객체에서 메서드를 호출하는지 확인합니다. 클래스에서 직접 호출하거나 클래스만 가리키는 변수에서 호출하는 경우와 구분하세요. 객체를 만들 때 생성자 인수를 전달했는지, 메서드를 호출할 때 일반 메서드 인수도 전달했는지 함께 확인합니다.
예를 들어 m = Delft는 클래스를 저장하고, 생성자가 이름을 받는 경우 m = Delft("Stack")는 인스턴스를 만듭니다. 그러면 m.fun()을 호출할 때 바인딩된 인스턴스가 자동으로 전달됩니다. 메서드에 인스턴스 데이터가 필요하지 않다면 @staticmethod를 고려하세요. 그렇지 않다면 인스턴스 메서드를 유지하고 호출 위치를 바로잡으세요.