들어가며
최근 `추천시스템` 예제 연습을하며 파이썬을 익히고 있는데요.
그 전에는 코딩테스트를 처음 공부할 때 파이썬을 썼었는데, 프로젝트 용으로 학습하다보니 어색한 문법이 있어서 학습 후 글을 추가해 둡니다.
예를 들어 이런걸 발견했습니다.
🤨 `self` 가 뭐길래 계속 호출해줘야 쓸 수 있는거지?
class MovieSimilarityCalculator:
def __init__(self, movies): # self 가 뭐지??
self.movies = movies # Movies 객체를 주입받음
Self 란?
Self는 클래스의 인스턴스를 나타냅니다. self
를 사용하면 파이썬에서 클래스의 attribute와 메서드에 액세스할 수 있습니다. 주어진 인수를 사용하여 어트리뷰트를 바인딩합니다.
클래스에서 생성된 객체의 메서드를 호출할 때마다 "self" 매개변수를 사용하여 객체가 자동으로 첫 번째 인수로 전달됩니다. 이를 통해 객체의 속성을 수정하고 해당 특정 인스턴스에 고유한 작업을 실행할 수 있습니다.
- Python은 명시적 철학을 따르는 언어라고합니다. (이부분은 제대로 이해를 못해서 다른 기회에 언어 철학을 이해하는 것으로...)
- 다른 언어(C++나 Java 등)에서 암묵적으로
this
를 사용하는 것과 달리, Python에서는self
를 명시적으로 추가해야 합니다.
다른 언어들도 암묵적으로 메서드의 첫번째 파라미터로 자기 자신을 가르키는 파라미터를 전달하기도 합니다만, `self` 로 매번 명시해주는 것이 신기했습니다.
참, 여기서 `self` 는 python 의 예약어가 아닌 그냥 기본 파라미터 이름이기 때문에 다른 이름으로 바꿔도 무방하다고 합니다 👍 그냥 무조건 그렇게 타입이 추론되는듯?
self 는 이런 특징을 갖습니다.
메모리에서 객체 인스턴스의 위치를 가르킵니다.
- 항상 현재 객체를 가리킵니다. 클래스의 인스턴스를 생성하면 기본적으로 자체 속성과 메서드 집합을 가진 객체를 생성하는 것입니다.
- 출처 : https://www.geeksforgeeks.org/self-in-python-class/
class Check:
def __init__(self):
print("Address of self = ",id(self))
obj = Check()
print("Address of class object = ",id(obj))
# Address of self = 140273244381008
# Address of class object = 140273244381008
인스턴스 변수에 접근할 수 있습니다.
self
를 사용하여 각 객체가 고유의 상태(변수 값)를 유지할 수 있도록 합니다. 예를 들어, 아래 코드에서 self.movies
는 해당 인스턴스의 movies
데이터를 참조합니다.
class Movies:
def __init__(self):
self.movies = {} # 각 인스턴스마다 고유한 movies 딕셔너리
동일 클래스임을 명시적으로 표현하기도 합니다. 아래 코드에서 self.jaccard_similarity
를 호출할 때 self
를 사용하여 동일한 클래스 내의 메서드에 접근합니다
class MovieSimilarityCalculator:
def jaccard_similarity(self, a, b):
if len(a) == 0 or len(b) == 0:
return 0
return len(a & b) / len(a | b)
def get_topk_jaccard_genres(self, target_mid, k=20):
# self를 사용하여 동일 클래스의 메서드 호출
similarity = self.jaccard_similarity(set1, set2)
여러 메서드가 self
를 통해 동일한 데이터를 참조할 수 있습니다.
아래 코드에서 self.movies
, self.genresets
같은 속성들은 self
를 통해 객체 전체에서 접근 가능합니다.
import csv
class Movies:
def __init__(self):
self.movies = {} # movie_id -> movie title
self.genresets = {} # movie_id -> set of genres
with open('./data/movies.csv', newline='') as csvfile:
csvreader = csv.reader(csvfile)
next(csvreader) # Skip header
for mid, title, genres in csvreader:
self.movies[int(mid)] = title
self.genresets[int(mid)] = set(genres.split('|'))
def get_movie_title(self, movie_id):
return self.movies.get(movie_id)
def get_movie_genres(self, movie_id):
return self.genresets.get(movie_id)
self를 빼면 어떻게 되나요?
만약 self
를 빼고 코드를 작성하면 Python은 그것을 인스턴스 속성이 아니라 지역 변수로 처리합니다.
class Movies:
def __init__(self):
movies = {} # 지역 변수로 처리됨
이 경우 movies
변수는 메서드가 끝나자마자 삭제되며, 다른 메서드에서 접근할 수 없습니다. 따라서, 인스턴스 변수로 사용하려면 반드시 self.movies
로 선언해야 합니다.