코딩도장 python 34~37장
34장. 클래스 사용하기
클래스 만들기
1
2
3
class 클래스이름:
def 메서드(self):
코드
1
2
3
class Person:
def greeting(self):
print("hello")
1
2
james = Person()
# james인스턴스 생성
메서드 호출
- 메서드는 클래스가 아니라 인스턴스를 통해 호출한다
1
2
3
james.greeting()
>>> hello
# 인스턴스를 통해 호툴하는 메서드를 인스턴스 메서드라고 부릅니다
인스턴스와 객체의 차이점
- 보통 객체만 지칭할 때는 그냥 객체(object)라고 부른다. 하지만 클래스와 연관지어 말할 때는 인스턴스라고 부릅니다
1
2
3
a = list(range(10))
b = list(range(20))
# 리스트 변수 a,b는 객체이며 a와 b는 list클래스의 인스턴스이다
메서드 안에서 메서드 호출하기
- 메서드 안에서 메서드를 호출할 때는 다음과 같이 self. 메서드() 형식으로 호출한다
- self 없이 메서드 이름만 사용하면 클래스 바깥쪽에 있는 함수를 호출한다는 뜻이다
1
2
3
4
5
6
7
8
9
class Person():
def greeting(self):
print("hello")
def hello(self):
self.greeting()
# self.메서드() 형식으로 클래스 안의 메서드를 호출
james = Person()
james.hello()
- 특정 클래스의 인스턴스인지 확인하는 방법은
1
2
isinstance(james, Person)
>>> True
속성 사용하기
- 클래스에서 속성을 만들고 사용하기
1
2
3
class 클래스이름:
def __init__(self):
self.속성 = 값
__innit__
메서드는 클래스에 ()(괄호)를 붙여서 인스턴스를 만들 때 호출되는 특별한 메서드 이다- __(밑줄 두개)가 붙은 메서드는 파이썬이 자동으로 호출해주는 메서드인데 스페셜 메서드(매직 메서드)라고 부른다
self의 의미
__init__
의 매개변수 self에 들어가는 값은 Person()이라 할 수 있다. 그리고 self가 완성된 뒤 james에 할당된다. 이후 메서드를 호출하면 현재 인스턴스가 자동으로 매개변수 self에 들어온다.
인스턴스를 만들 때 값 받기
- 인스턴스를 통해 접근하는 속성을 인스턴스 속성이라고 한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Person():
def __init__(self, name, age, address):
# self 다음에 name, age, address를 지정
self.hello = "hi"
self.name = name
# 메서드 안에서는 위와 같이 매개변수를 그대로 self에 넣어서 속성으로 만듬
self.age = age
self.address = address
def greeting(self):
print(f"{self.hello}저는 {self.name}입니다")
# name속성에 접근하기 위해 self.name으로 사용한다
maria = Person("마리아", 20, "서울시 서초구 반포동")
# 변수에 할당하고 그 내용이 채워져 maria 인스턴스가 만들어짐
# Person의 괄호 안에 넣은 값은 __init__ 메서드에서 self뒤에 있는 매개변수에 차례데로 들어간다
maria.greeting()
print("이름:", maria.name)
print("나이:", maria.age)
print("주소:", maria.address)
>>>
안녕하세요. 저는 마리아 입니다.
이름 : 마리아
나이 : 20
주소 : 서울시 서초구 반포동
__slots__
1
2
3
4
class Person:
__slots__ = ["name", "age"]
# name, age만 허용(다른 속성은 생성 제한)
# 허용되지 않은 속성은 추가할 떄 에러가 발생
클래스 위치인수 & 키워드 인수
- 위치 인수
1
2
3
4
5
6
7
class Person:
def __init__(self, *args): # 위치 인수
self.name = args[0]
self.age = args[1]
self.address = args[2]
maria = Person(*['마리아', 20, '서울시 서초구 반포동'])
- 키워드 인수
1
2
3
4
5
6
7
8
class Person:
def __init__(self, **kwargs): # 키워드 인수
self.name = kwargs['name']
self.age = kwargs['age']
self.address = kwargs['address']
maria1 = Person(name='마리아', age=20, address='서울시 서초구 반포동')
maria2 = Person(**{'name': '마리아', 'age': 20, 'address': '서울시 서초구 반포동'})
비공개 속성(private attribute)
- 클래스 바깥에서는 접근할 수 없고 클래스 안에서만 사용할 수 있다
1
2
3
4
5
6
7
8
9
10
11
class Person:
def __init__(self, name, age, address, wallet):
self.name = name
self.age = age
self.address = address
self.__wallet = wallet
# 변수 앞에 __를 붙여서 비공개 속성으로 만듦
maria = Person('마리아', 20, '서울시 서초구 반포동', 10000)
maria.__wallet -= 10000
# 클래스 바깥에서 비공개 속성에 접근하면 에러가 발생함
비공개 메서드
- 속성 뿐 아니라 메서드도 이름이 __(밑줄 두개)로 시작하면 클래스 안에서만 호출할 수 있는 비공개 메서드가 된다
- 보통 내부에서만 호출되어야 하는 메서드를 비공개 메서드로 만든다
1
2
3
4
5
6
7
8
9
10
11
class Person:
def __greeting(self):
print('Hello')
def hello(self):
self.__greeting()
# 클래스 안에서는 비공개 메서드를 호출할 수 있음
james = Person()
james.__greeting()
# 에러: 클래스 바깥에서는 비공개 메서드를 호출할 수 없음
35장. 클래스 속성와 정적, 클래스 메서드 사용하기
클래스 속성
- 클래스 속성은 클래스에 속해 있으며, 모든 인스턴스에서 공유한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Person:
bag = []
def put_bag(self, stuff):
self.bag.append(stuff)
# 클래스 속성에 접글 할 때는 클래스 이름으로 접근해야 한다
# 수정해야되는 코드
# Person.bag.append(stuff)
james = Person()
james.put_bag('책')
maria = Person()
maria.put_bag('열쇠')
print(james.bag)
print(maria.bag)
>>>
["책", "열쇠"]
["책", "열쇠"]
속성, 메서드 이름을 찾는 순서
- 파이썬에서는 속성, 메서드 이름을 찾을 때 인스턴스, 클래스 순으로 찾는다. 그래서 인스턴스 속성이 없으면 클래스 속성을 찾게 되므로 james.bag이 잘 동작한다
인스턴스 속성
- 여러사람이 가방을 공유하지 않으려면 인스턴스 속성으로 만들면 된다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person:
def __init__(self):
self.bag = []
def put_bag(self, stuff):
self.bag.append(stuff)
james = Person()
james.put_bag('책')
maria = Person()
maria.put_bag('열쇠')
print(james.bag)
print(maria.bag)
>>>
["책"]
["열쇠"]
# 인스턴스 속성은 인스턴스별로 독립되어 있으며, 서로 영향을 주지 않는다
- 클래스 속성 : 모든 인스턴스가 공유, 인스턴스 전체가 사용해야 하는 값을 저장할 때 사용한다
- 인스턴스 속성 : 인스턴스별로 독립되어 있음, 각 인스턴스가 값을 따로 저장해야 할 때 사용한다
정적 메서드
- 인스턴스를 통하지 않고 클래스에서 바로 호출할 수 있다
- 보통 인스턴스 속성, 인스턴스 메서드가 필요 없을 때 사용한다
- 메서드의 실행이 외부 상태에 영향을 끼치지 않는 순수 함수를 만들 때 사용한다
1
2
3
4
5
6
7
8
9
10
11
class Calc:
@staticmethod
def add(a, b):
print(a + b)
@staticmethod
def mul(a, b):
print(a * b)
Calc.add(10, 20) # 클래스에서 바로 메서드 호출
Calc.mul(10, 20) # 클래스에서 바로 메서드 호출
클래스 메서드
- 정적 메서드처럼 인스턴스 없이 호출할 수 있다는 점은 같지만, 클래스 메서드는 메서드 안에서 클래스 속성, 클래스 메서드에 접근해야 할 때 사용한다
- cls를 사용하면 메서드 안에서 현재 클래스의 인스턴스를 만들 수도 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Person:
count = 0 # 클래스 속성
def __init__(self):
Person.count += 1
# 인스턴스가 만들어질 때
# 클래스 속성 count에 1을 더함
@classmethod
def print_count(cls):
print('{0}명 생성되었습니다.'.format(cls.count))
# cls로 클래스 속성에 접근
james = Person()
maria = Person()
Person.print_count()
# 2명 생성
@classmethod
def create(cls):
p = cls()
# cls()로 인스턴스 생성
return p
36장. 클래스 상속 사용하기
상속(inheritance)
- 물려받는 기능을 유지한 채로 다른 기능을 추가할 때 사용하는 기능
- 부모클래스 (슈퍼클래스) - 자식클래스(서브클래스)
- 새로운 기능이 필요할 때마다 계속 클래스를 만든다면 중복되는 부분을 반복해야 하므로, 이런 중복되는 기능을 만들지 않으려고 즉 기존 기능을 재사용 할 수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
class Person():
def greeting(self):
print("hi")
class Student(Person):
def study(self):
print("study")
james = Student()
james.greeting()
# 안녕하세요.: 기반 클래스 Person의 메서드 호출
james.study()
# 공부하기: 파생 클래스 Student에 추가한 study 메서드
- 상속 관계를 확인하기 위해 issubclass(Student, Person)을 사용한다
상속 관계 & 포함 관계
- 상속관계 : 명확하게 같은 종류, 동등한 관계일때 사용, is-a관계라고 부른다.
- 포함관계 : 상속관계 이외에 속성에 인스턴스를 넣는 방식, has-a관계
1
2
3
4
5
6
7
8
9
10
11
12
13
# 포함관계의 예
class Person:
def greeting(self):
print('안녕하세요.')
class PersonList():
def __init__(self):
self.person_list = []
# 리스트 속성에 Person 인스턴스를 넣어서 관리
def append_person(self, person):
# 리스트 속성에 Person 인스턴스를 추가하는 함수
self.person_list.append(person)
부모클래스 사용하기 super()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person:
def __init__(self):
print('Person __init__')
self.hello = '안녕하세요.'
class Student(Person):
def __init__(self):
print('Student __init__')
super().__init__()
# super()로 기반 클래스의 __init__ 메서드 호출
self.school = '파이썬 코딩 도장'
james = Student()
print(james.school)
print(james.hello)
1
2
3
4
5
6
7
8
class Student(Person):
def __init__(self):
print('Student __init__')
super(Student, self).__init__()
# super(파생클래스, self)로 기반 클래스의 메서드 호출
self.school = '파이썬 코딩 도장'
# 좀 더 명확하게 super사용하기
메서드 오버라이딩 사용하기
- 자식클래스에서 부모클래스의 메서드를 새로 정의하는 것
1
2
3
4
5
6
7
8
9
10
11
class Person:
def greeting(self):
print('안녕하세요.')
class Student(Person):
def greeting(self):
print('안녕하세요. 저는 파이썬 코딩 도장 학생입니다.')
# Person클래스의 greeting메소드를 무시하고 Student 클래스에서
# 새로운 greeting메서드를 만듬
james = Student()
james.greeting()
- 부모 클래스의 메서드를 재활용 하면 중복을 줄일 수 있기 때문에 , 원래 기능을 유지하면서 새로운 기능을 덧붙일 때 사용한다
다중상속
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Person:
def greeting(self):
print('안녕하세요.')
class University:
def manage_credit(self):
print('학점 관리')
class Undergraduate(Person, University):
def study(self):
print('공부하기')
james = Undergraduate()
james.greeting()
# 안녕하세요.: 기반 클래스 Person의 메서드 호출
james.manage_credit()
# 학점 관리: 기반 클래스 University의 메서드 호출
james.study()
# 공부하기: 파생 클래스 Undergraduate에 추가한 study 메서드
다이아몬드 상속
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A:
def greeting(self):
print('안녕하세요. A입니다.')
class B(A):
def greeting(self):
print('안녕하세요. B입니다.')
class C(A):
def greeting(self):
print('안녕하세요. C입니다.')
class D(B, C):
pass
x = D()
x.greeting() # 안녕하세요. B입니다.
Object클래스
- object는 모든 클래스의 조상이다.
추상 클래스
- 메서드의 목록만 가진 클래스, 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용
- import로 abc모듈을 가져와야 한다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from abc import *
class StudentBase(metaclass=ABCMeta):
@abstractmethod
def study(self):
pass
@abstractmethod
def go_to_school(self):
pass
class Student(StudentBase):
def study(self):
print('공부하기')
def go_to_school(self):
print('학교가기')
james = Student()
james.study()
james.go_to_school()
- 추상 클래스는 자식 클래스가 반드시 구현해야 하는 메서드를 정해줄 수 있다
-
추상클래스의 추상 메서드를 모두 구현했는지 확인하는 시점은 자식 클래스가 인스턴스를 만들 때 이다. 따라서 james= Student()에서 확인한다
- 추상 클래스는 인스턴스를 만들 수 없기 때문에 추상 메서드도 호출할 일이 없어 추상메서드를 빈 메서드로 만든다
1
2
3
4
5
6
7
8
9
@abstractmethod
def study(self):
pass
# 추상 메서드는 호출할 일이 없으므로 빈 메서드로 만듦
@abstractmethod
def go_to_school(self):
pass
# 추상 메서드는 호출할 일이 없으므로 빈 메서드로 만듦
- 추상 클래스는 인스턴스로 만들때는 사용하지 않고, 오로지 상속에서만 사용한다