# 클래스
## 클래스 선언
```python
class ClassName():
def __init__(self, arg):
seft.arg = arg
instance = ClassName('this is arg')
```
클래스가 동작하는 과정은 다음과 같다.
- ClassName 의 정의를 찾는다
- 새 객체를 메모리에 초기화(생성)한다
- 객체의 \_\_init__ 메서드를 호출한다
- 새롭게 생성된 객체를 self에 전달하고, 인자('this is arg')를 arg에 전달한다
- 객체에 arg 값을 저장한다
- 새로운 객체를 반환한다
- instance에 이 객체를 연결한다
모든 클래스 정의에서 \_\_init__ 메서드를 가질 필요는 없다.
## 상속
```python
class Car():
def exclaim(self):
print("I'm a Car!")
class Yugo(Car):
def exclaim(self):
print("I'm a Yugo!")
def need_a_push(self)
print("A little help here?")
car = Yugo()
car.exclaim() # I'm a Car!
```
자식 클래스는 부모 클래스에 없는 메서드를 추가할 수 있다.
### 메서드 오버라이드
```python
class Person():
def __init__(self, name):
self.name = name
class MDPerson(Person):
def __init__(self, name):
self.name = "Doctor " + name
class JDPerson(Person):
def __init__(self, name):
self.name = name + ", Esquire"
```
이러한 경우 \_\_init__ 초기화 메서드는 부모 클래스의 Person과 같은인자를 취하지만 객체의 인스턴스 내부에서는 다른 name 값을 저장한다.
### 부모에게 도움 받기: super
자식 클래스에서 부모 클래스의 메서드를 호출하려면 super() 메서드를 사용한다.
자식 클래스에서 \_\_init__() 메서드를 정의하면 부모 클래스의 \_\_init__() 메서드를 대체하기 때문에, 부모 클래스의 \_\_init__() 메서드가 호출되지 않으므로 명시적으로 호출해야 한다.
```python
class Person():
def __init__(self, name):
self.name = name
class EmailPerson(Person):
def __init__(self, name, email):
super().__init__(name)
self.email = email
```
- super() 메서드는 부모 클래스의 정의를 얻는다
- \_\_init__() 메서드는 Person.\_\_init__() 메서드를 호출한다. 이 메서드는 self 인자를 슈퍼 클래스로 전달하는 역할을 하기 때문에 어떤 선택적 인자를 제공하기만 하면 된다. 이 경우 Person() 에게서 받는 인자는 name이다.
- self.email = email 은 EmailPerson 클래스를 Person 클래스와 다르게 만들어주는 새로운 코드이다.
## 메서드 타입
클래스 정의에서 첫 번째 인자가 self라면 이 메서드는 인스턴스 메서드(instance method)이다.
이와 반대로 클래스 메서드(class method)는 클래스 전체에 영향을 미친다. 클래스에 대한 어떤 변화는 모든 객체에 영향을 미친다. 클래스 정의에서 함수에 `@classmethod` 데커레이터가 있다면 이것은 클래스 메서드이다. 또한 이 메서드의 첫 번째 매개변수는 클래스 자신이다. 보통 `cls`로 쓴다.
```python
class A():
count = 0
def __init__(self):
A.count += 1
def exclaim(self):
print("I'm a A!")
@classmethod
def kids(cls):
print("A has", cls.count, "little objects.")
```
```
easy_a = A()
breezy_a = A()
wheezy_a = A()
A.kids() # A has 3 little objects.
```
정적 메서드(static method)는 @staticmethod 데커레이터가 붙어 있고, 첫 번째 매개변수로 `self`나 `cls`가 없다.
```python
class CoyoteWeapon():
@staticmethod
def commercial():
print('This CoyoteWeapon has been brought to you by Acme')
```
```
CoyoteWeapon.commercial() # This ~~
```
이 메서드를 접근하기 위해 객체를 따로 생성할 필요가 없다.