점프투파이썬 참고
클래스는 프로그래밍에 필수요소는 아니지만 적재적소에 잘 사용하면 얻을 수 있는 이익이 많다.
예를 들어 별 모양 쿠키를 굽는다고 하자 1~2개 정도면 손으로 하트모양을 직접 만들어 구울 수 있지만, 만약 100개를 만든다면 너무 힘들 것이다. 그럴 때 별모양 틀이 있다면 훨씬 수월하게 100개의 쿠키를 만들 수 있다. 여기서 별모양 틀이 Class이다.
똑같은 작업이 여러번 필요할 때, 함수를 여러개 만들 필요없이 Class를 만들면 훨씬 간편할 것이다.
위의 예제에서 쿠키는 객체(object)가 되겠다.
클래스로 만든 객체에는 중요한 특징이 있다. 바로 객체마다 고유한 성격을 가진다는 것이다. 쿠키마다 초코를 입히거나 구멍을 뚫어도 다른 과자에는 아무 영향이 없는 것처럼 말이다.
class Cookie:
pass
a = Cookie()
b = Cookie()
클래스로 만든 객체를 인스턴스라고도 한다.
a = Cookie() 이렇게 만든 a는 객체이다. 그리고 a 객체는 Cookie의 인스턴스이다.
즉, 인스턴스라는 말은 특정 객체(a)가 어떤 클래스(Cookie)의 객체인지를 관계 위주로 설명할 때 사용한다.
"a는 인스턴스"보다는 "a는 객체"라는 표현이 어울리며 "a는 Cookie의 객체"보다는 "a는 Cookie의 인스턴스"라는 표현이 훨씬 잘 어울린다.
클래스는 무작정 만드는 것보다 클래스로 만든 객체를 중심으로 어떤 식으로 동작하게 할 것인지 미리 구상을 한 후에 생각한 것들을 하나씩 해결하면서 완성해 나가는 것이 좋다.
1. 객체중심으로 구상하기
1) a라는 객체를 만든다. a=FourCal()
2) 숫자 지정 a.setdata(4,2)
3) add 메소드 print(a.add()) >>6
4) mul 메소드 print(a.mul()) >>8 (곱셈)
5) sub 메소드 print(a.sub()) >>2 (뺄셈)
6) div 메소드 print(a.div()) >>2 (나눗셈)
2. 클래스 구조 만들기
1) 틀 만들기
: 아무 변수나 함수도 포함하지 않지만 객체a를 만들 수 있는 기능이 있다.
⁕ pass는 아무것도 수행하지 않는 문법으로 임시로 코드를 작성할 때 주로 사용한다.
class Fourcal:
pass
2) a 객체는 FourCal 클래스의 객체임을 알 수 있다.
a = Forcal()
type(a)
>> <class '__main__.Fourcal'>
3. 객체에 숫자 지정할 수 있게 만들기
아직 생성된 객체 a는 아무런 기능을 하지 못한다. 사칙연산 기능을 하는 객체를 만들기 전에 사용할 2개의 숫자를 지정하는 함수를 만들어보자.
1) 함수만들기
앞에서 만든 pass문장을 삭제하고 그 대신 setdata 함수를 만들었다. 클래스 안에 구현된 함수는 다른 말로 메서드(Method) 라고 한다. 앞으로 클래스 내부의 함수는 항상 메서드라고 표현할 테니 기억해두자.
일반적인 함수 만드는 법
class FourCal:
def setdata(self, first, second): #메서드의 매개변수
self.first = first #메서드의 수행문1
self.second = second #메서드의 수행문2

파이썬 메서드의 첫 번째 매개변수 이름은 관례적으로 self를 사용한다. 객체를 호출할 때 호출한 객체 자신이 전달되기 때문에 self를 사용한 것이다. (self말고 다른 이름을 사용해도됨)
파이썬만의 독특한 특징이다. 자바같은 언어는 첫번째 매개변수 self가 필요없다.

setdata 메서드 수행문

2) a,b 객체만들기
a의 객체 first값은 b객체 first에 영향을 받지 않고 원래 값을 유지하고 있음을 확인할 수 있다. 클래스로 만든 객체의 객체변수는 다른 객체의 객체변수에 상관없이 독립적인 값을 유지한다.
a = FourCal()
b = FourCal()
a.setdata(4,2)
b.setdata(3,7)
print(a.first)
print(b.second)
>>4
>>7
id 함수
※ id 함수는 객체의 주소를 돌려주는 파이썬 내장 함수이다.
a 객체의 first 주소 값과 b 객체의 first 주소 값이 서로 다르므로 각각 다른 곳에 그 값이 저장된다는 것을 알 수 있다. 객체변수는 그 객체의 고유 값을 저장할 수 있는 공간이다. 객체 변수는 다른 객체들 영향받지 않고 독립적으로 그 값을 유지한다는 점을 꼭 기억하자. 클래스에서는 이 부분을 이해하는 것이 가장 중요하다.id(a.first) # a의 first 주소값을 확인 1839194944 id(b.first) # b의 first 주소값을 확인 1839194928
4. 더하기 기능 만들기
class FourCal:
def setdata(self, first, second):
self.first = first
self.second = second
def add(self):
result = self.first + self.second
return result
a = FourCal()
a.setdata(4, 2)
print(a.add())
>>6
add 메서드의 매개변수는 self이고 반환 값은 result이다.
a.add()와 같이 a 객체에 의해 add메서드가 수행되면서 add메서드의 self에는 객체 a가 자동으로 입력되므로 위의 내용은 result= a.first + a.second 즉, result=4+2와 같이 해석한다.
4. 다른기능 더 추가하기
class FourCal:
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
a = FourCal()
b = FourCal()
a.setdata(4,2)
b.setdata(3,8)
a.add()
>>6
b.mul()
>>24
a.sub()
>>2
b.div()
>>0.375
>>> 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'
__init__을 사용하면 이 매서드는 생성자가 된다.__init__ 메서드는 setdata메서드와 이름만 다르고 모든게 동일하다.__init__으로 했기 때문에 생성자로 인식되어 객체가 생성되는 시점에 자동으로 호출되는 차이가 있다.class FourCal:
def __init__(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
a = FourCal()을 수행하면 생성자 __init__이 호출되어 오류가 발생한다. 오류가 발생한 이유는 생성자의 매개변수 first와 second에 해당하는 값이 전달되지 않았기 때문이다. 오류를 해결하려면 first와 second에 해당하는 값을 전달해 객체를 생성해야 한다.a = FourCal(4,2)

__init__메서드도 다른 메서드와 마찬가지로 첫 번째 매개변수 self에 생성되는 객체가 자동으로 전달된다는 점을 기억하자. 따라서 __init__메서드가 호출되면 setdata 메서드를 호출했을때와 마찬가지로 first, second라는 객체변수가 생성될 것이다.
상속이란 '물려받다'라는 뜻으로 '재산을 상속받다'라고 할 때의 상속과 같은 의미이다. 클래스에도 이 개념을 적용할 수 있다. 어떤 클래스를 만들 때 다른 클래스의 기능을 물려받을 수 있게 만드는 것이다. 이번에는 상속 개념을 사용해 FourCal 클래스에 a의 b제곱을 구할 수 있는 기능을 추가해보자.
1) 상속하기
MoreFourCal 클래스는 FourCal 클래스를 상속했으며로 FourCal 클래스의 모든 기능을 사용할 수 있어야한다.
class MoreFourCal(FourCal):
pass
a = MoreFourCal(4,2)
a.add()
>>6
2) a의 b제곱을 계산하는 함수만들기
패스문장은 삭제하고 새 함수를 만들자.
class MoreFourCal(FourCal):
def pow(self):
result = self.first ** self.second
return result
a = MoreFourCal(4,2)
a.pow()
>>16
FourCal 클래스의 객체 a에 4,0을 설정하고 div메서드를 호출하면 ZeroDivisionError 오류가 발생한다.

SafeFourCal 클래스는 FourCal 클랫에 있는 div 메서드를 동일한 이름으로 다시 작성하였다.
이렇게 부모 클래스(상속한 클래스)에 있는 메서드를 동일한 이름으로 다시 만드는 것을 메서드 오버라이딩(Overriding, 덮어쓰기)이라고 한다. 이렇게 메서드를 오버라이딩하면 부모클래스의 메서드 대신 오버라이딩한 메서드가 호출된다.
class SafeFourCal(FourCal):
def div(self):
if self.second == 0 : #나누는 값이 0인경우 0을 리턴하도록 수정
return 0
else:
return self.first/self.second
a = SafeFourCal(4,0)
a.div()
>> 0
객체변수는 다른 객체들에 영향을 받지 않고 독립적으로 그 값을 유지한다는 점을 이미 알아보았다. 클래스 변수는 객체변수와는 성격이 다르다.
Family 클래스에 선언한 lastname이 바로 클래스 변수이다. 클래스 변수는 클래스 안에 함수를 선언하는 것과 마찬가지로 클래스 안에 변수를 선언하여 생성한다.
class Family:
lastname = "김"
print(Family.lastname)
>> 김
클래스 변수는 클래스이름.클래스변수로 사용할 수 있다. 또는 Family 클래스로 만든 객체를 통해서도 클래스 변수를 사용할 수 있다. 또한 클래스 변수 값을 변경하면 클래스로 만든 객체의 lastname 값도 모두 변경된다는 것을 확인할 수 있다.
a = Family()
b = Family()
print(a.lastname)
>>김
print(b.lastname)
>>김
Family.lastname ="박"
print(a.lastname)
>>박
print(a.lastname)
>>박
id함수를 사용하면 클래스 변수가 공유된다는 사실을 증명할 수 있다.
Family.lastname = a.lastname = b.lastname

클래스 변수보다 객체변수가 훨씬 중요하다. 실무 프로그래밍을 할 때도 클래스변수보다 객체변수를 사용하는 비율이 훨씬 높다.