archive
클래스 본문
1. 클래스 (Class) 와 객체 (Object)

과자틀 = 클래스, 과자 틀로 찍어낸 과자 = 객체
클래스로 만든 객체에는 중요한 특징이 있는데, 바로 객체마다 고유한 성격을 가진다는 것이다
동일한 클래스로 만든 객체들은 서로 전혀 영향을 주지 않는다.
>>> a = Cookie()
>>> b = Cookie()
Cookie의 결과값을 리턴 받는 변수 a와 b가 객체
마치 함수를 사용하여 그 결과값을 리턴받는 모습과 유사하다
** 객체와 인스턴스의 차이
a = Cookie() 로 만든 a는 객체이다, 그리고 a 객체는 Cookie 클래스의 인스턴스이다.
즉 인스턴스라는 말은 특정 객체(a)가 어떤 클래스(Cookie)의 객체인지는 관계 위주로 설명할 때 사용한다.
2. 클래스 구조 만들기
>>> class FourCal:
... def __init__(self, first, second):
... self.first = first
... self.second = second
... def setdata(self, first, second):
... self.first = first
... self.second = second
... def add(self):
... result = self.first + self.second
... return result
... def mul(self):
... result = self.first * self.second
... return result
... def sub(self):
... result = self.first - self.second
... return result
... def div(self):
... result = self.first / self.second
... return result
클래스 안에 구현된 함수는 다른 말로 메서드라고 부른다. ** 함수와 메서드 차이 -> 클래스 안에 구현 밖에 구현
(1) setdata 메서드의 매개 변수
setdata 메서드는 매개변수로 self, first, second 3개의 입력값을 받는다.

메서드 사용 시에는 매개변수를 self를 제외한 두 개만 입력하면 되는데, 이는 위의 그림과 같이 매개변수가 전달되는 구조를 가지고 있기 때문이다.
즉, a.setdata(4, 2)처럼 호출하면 setdata 메서드의 첫 번째 매개변수 self에는 setdata 메서드를 호출한 객체 a가 자동으로 전달된다.
파이썬 메서드의 첫 번째 매개변수 이름은 관례적으로 self를 사용한다, 객체를 호출할 때 호출한 객체 자신이 전달되기 때문에 self라는 이름을 사용한 것, 물론 self 말고 다른 이름을 사용해도 상관 없다
** 메서드의 첫 번째 매개변수 self를 명시적으로 구현하는 것은 파이썬만의 독특한 특징임
(2) 생성자
>>> a = FourCal()
>>> a.add()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in add
AttributeError: 'FourCal' object has no attribute 'first'
이렇게 객체에 first와 second같은 초깃값을 설정해야 할 필요가 있을 때에는 setdata와 같은 메서드를 호출하여 초깃값을 설정하기 보다 생성자를 구현하는 것이 안전한 방법이다.
생성자 (Constructor)란 객체가 생성될 때 자동으로 호출되는 메서드를 의미
파이썬 메서드 명으로 __init__을 사용하면 이 메서드는 생성자가 된다
__init__ 메서드는 setdata 메서드와 이름만 다르고 모든 것이 동일하다
단, 메서드 이름을 __init__으로 했기 때문에 생성자로 인식되어 객체가 생성되는 시점에 자동으로 호출된다는 차이가 존재한다.
>>> a = FourCal()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() missing 2 required positional arguments: 'first' and 'second'
a = FourCal()을 수행할 때 생성자 __init__가 호출되어 위와 같은 오류가 발생했다. 오류가 발생한 이유는 생성자의 매개변수 first와 second에 해당하는 값이 전달되지 않았기 때문이다.
이 오류를 해결하려면 first와 second에 해당하는 값을 전달하여 객체를 생성해야 한다.
>>> a = FourCal(4, 2)
위와 같이 수행하면 __init__ 메서드의 매개변수에는 각각 다음과 같은 값이 전달된다.
매개변수 | 값 |
self | 생성되는 객체 |
first | 4 |
second | 2 |
3. 클래스의 상속
상속(Inheritance)는 물려받다라는 뜻으로, 어떤 클래스를 만들 때 다른 클래스의 기능을 물려받을 수 있게 만드는 것
>>> class MoreFourCal(FourCal):
...
클래스를 상속하기 위해서는 다음처럼 클래스 이름 뒤 괄호 안의 매개변수로 상속할 클래스 이름을 넣어주면 된다
=> class 클래스이름(상속할클래스이름)
MoreFourCal 클래스는 FourCal 클래스를 상속했으므로 FourCal 클래스의 모든 기능을 사용할 수 있다.
>>> a = MoreFourCal(4, 2)
>>> a.add()
6
>>> a.mul()
8
>>> a.sub()
2
>>> a.div()
2
상속받은 FourCal 클래스의 기능을 모두 사용할 수 있다는 것을 확인 가능
** 상속 기능을 사용하는 이유
보통 상속으 기존 클래스를 변경하지 않고 기능을 추가하거나 기존 기능을 변경하려고 할 때 사용한다
특히 기존 클래스가 라이브러리 형태로 제공되거나 수정이 허용되지 않는 상황이라면 상속을 사용해야한다
>>> class MoreFourCal(FourCal):
... def pow(self):
... result = self.first ** self.second
... return result
>>> a = MoreFourCal(4, 2)
>>> a.pow()
16
>>> a.add()
6
상속은 MoreFourCal 클래스처럼 기존 클래스(FourCal)는 그대로 놔둔 채 클래스의 기능을 확장할 때 주로 사용한다.
상속 시 부모의 instance 속성은 물려지지 않는다.
********* 중요 !
자식 클래스에서 생성자를 만들지 않은 경우와 새로 만들 경우에 차이가 발생한다. 자식 클래스에서 생성자를 만들지 않은 경우, 자식 클래스의 instance 생성시 부모 클래스의 생성자를 자동으로 호출한다.
자식 클래스에서 생성자를 새로 만든 경우, 부모 클래스의 생성자는 자동으로 호출되지 않는다. 부모 클래스의 생성자를 호출하기 위해서는 super() 함수를 통해서 호출하거나, 부모 클래스명을 이용해 직접 생성자를 호출해야한다. 두 함수의 차이는 아래와 같다.
- Parent.__init__(self)방식은 부모클래스의 생성자 메소드를 직접 참고하기 때문에, 부모클래스가 변경될 경우 Child(Parent), Parent.function() 둘 다 변경해줘야한다.
- super(Child, self).__init__방식은 부모클래스를 자동으로 인식하므로, 부모 클래스를 변경할 경우, Child(Parent) 부분만 변경해주면 된다.
- 생성자 초기화시 super()함수는 자동으로 self가 전달되지만, 직접 호출시에는 self도 전달해야한다.
4. 메서드 오버라이딩
>>> class SafeFourCal(FourCal):
... def div(self):
... if self.second == 0: # 나누는 값이 0인 경우 0을 리턴하도록 수정
... return 0
... else:
... return self.first / self.second
이렇게 부모 클래스(상속한 클래스)에 있는 메서드를 동일한 이름으로 다시 만드는 것을 메서드 오버라이딩(method overriding)이라고 한다.
이렇게 메서드를 오버라이딩하면 부모 클래스의 메서드 대신 오버라이딩한 메서드가 호출된다.
5. 클래스 변수
객체변수는 다른 객체들의 영향을 받지 않고 그 값을 유지한다
클래스 변수는 아님!
즉 클래스 변수는 생성자의 매개변수로 전달받아서 생성되는 객체만의 변수가 아니라 공통된 값을 가지는 변수임
>>> class Family:
... lastname = "김"
Family 클래스에 선언한 lastname이 바로 클래스변수이다.
클래스변수는 클래스 안에 함수를 선언하는 것과 마찬가지로 클래스 안에 변수를 선언하여 생성한다.
>>> Family.lastname
김
클래스변수는 위 예와 같이 클래스_이름.클래스변수로 사용할 수 있다.
즉, 클래스변수는 객체변수와 달리 클래스로 만든 모든 객체에 공유된다는 특징이 있다.
점프투 파이썬의 내용 참고해서 작성됨, https://wikidocs.net/28
05-1 클래스
초보 개발자들에게 클래스(class)는 넘기 힘든 장벽과도 같은 존재이다. 독자들 중에도 클래스라는 단어를 처음 접하는 이들이 있을 것이다. 그러면 도대체 클래스가 무엇인지, 클…
wikidocs.net
** Seq2Seq 코드에 클래스 살펴보기
class Encoder(nn.Module):
def __init__(self, input_dim, embed_dim, hidden_dim, n_layers, dropout_ratio):
super().__init__()
# 임베딩(embedding)은 원-핫 인코딩(one-hot encoding)을 특정 차원의 임베딩으로 매핑하는 레이어
self.embedding = nn.Embedding(input_dim, embed_dim)
# LSTM 레이어
self.hidden_dim = hidden_dim
self.n_layers = n_layers
self.rnn = nn.LSTM(embed_dim, hidden_dim, n_layers, dropout=dropout_ratio) # torch에 LSTM 함수가 존재...!
# 드롭아웃(dropout)
self.dropout = nn.Dropout(dropout_ratio)
# 인코더는 소스 문장을 입력으로 받아 문맥 벡터(context vector)를 반환 -> Seq2Seq 특징 : 하나의 문맥 벡터에 모든 문맥을 담음
#문맥 벡터는 가장 마지막 hidden layer을 채택
def forward(self, src):
# src: [단어 개수, 배치 크기]: 각 단어의 인덱스(index) 정보
embedded = self.dropout(self.embedding(src))
# embedded: [단어 개수, 배치 크기, 임베딩 차원]
outputs, (hidden, cell) = self.rnn(embedded)
# outputs: [단어 개수, 배치 크기, 히든 차원]: 현재 단어의 출력 정보
# hidden: [레이어 개수, 배치 크기, 히든 차원]: 현재까지의 모든 단어의 정보
# cell: [레이어 개수, 배치 크기, 히든 차원]: 현재까지의 모든 단어의 정보
# 문맥 벡터(context vector) 반환
return hidden, cell
** super() 함수는 부모 클래스의 임시적인 객체를 반환하여 부모 클래스의 메소드를 사용할 수 있게 하는 것

우리는 이 예시에서 "부모 클래스의 인스턴스 속성은 자식 클래스에 상속되지 않는다" 는 걸 알았습니다.
인스턴스 속성이 언제 생기는지를 생각해보면 간단해 집니다.
위의 예시에서 부모 클래스의 인스턴스 속성은 부모 클래스 객체가 형성될때 __init__ 매직 메소드가 실행되면서 생성 될 것입니다.
그러나 자식 클래스 어디에도 부모 클래스의 객체가 형성된 적이 없지요.
그래서 super()라는 함수를 이용하여 부모 클래스의 __init__() 매직 메소드를 자식 클래스에 실행시키면 문제가 해결됩니다!!
그것이 바로 super().__init__() 의 사용 이유입니다.
부모 클래스의 __init__() 매직 메소드를 자식 클래스의 __init__() 매직 메소드에서 실행 한다 고 생각하시면 됩니다.
즉, 자식 클래스에도 부모 클래스의 인스턴스 속성과 동일한 속성이 생성되는 것입니다.
class Human:
""" Super Class """
def __init__(self):
# instance 속성!!
self.name = '사람이름'
self.age = '나이'
self.city = '사는도시'
def show(self):
print('사람 클래스의 메소드입니다.')
class Student(Human):
""" Child Class """
def __init__(self,name):
super().__init__()
self.name = name
def show_name(self):
print('사람의 이름은 : ',self.name)
def show_age(self):
print('사람의 나이는 : ',self.age)
a = Student('james')
a.show() # 메소드 상속
a.show_age() # 인스턴스 속성 상속
a.show_name() # 자식노드에서 속성을 변경
'Python > Python 코테 준비' 카테고리의 다른 글
sort 기준 정의 (0) | 2024.09.22 |
---|---|
그래프 탐색 알고리즘 (Graph Search Algorithm) (0) | 2024.08.22 |
Sliding window (0) | 2024.08.15 |
python coding test hack (0) | 2024.08.14 |
Numpy 라이브러리 (2) (0) | 2024.05.01 |