클래스 합성

매일 공부(ML)·2022년 6월 29일
0

이어드림

목록 보기
87/146

파이썬이 동적 언어라는 것을 이용하라

  • 동적(dynamic)

    • 어떤 값이 들어올지 미리 알 수 없는 식별자유지
#예시
#학생들의 점수를 기록할 때, 학생의 이름을 모르는 경우

"""
학생별로 미리 정의된 애트리뷰트 사용대신 딕셔너리에 이름을 저장하는 클래스 정의
"""

class SimpleGradebook:
    def __init__(self):
        self._grades = {}

    def add_student(self, name):
        self._grades[names] = []

    def report_grade(self, name, score):
        self._grades[name].append(score)

    def average_grade(self, name):
        grades = self._grades[name]
        return sum(grades) / len(grades)

book = SimpleGradebook()
book.add_student('아이작 뉴턴')
book.report_grade('아이작 뉴턴', 90)
book.report_grade('아이작 뉴턴', 95)
book.report_grade('아이작 뉴턴', 85)

print(book.average_grade('아이작 뉴턴')) #90.0
  • 위의 코드는 너무 확장을 많이 해서 깨지기 쉬운 코드

  • 코드를 변경해도 가독성이 떨어질 확률이 높다.


해결책:클래스 계층 구조를 사용

  • 내포 단계가 두 단계 이상일 경우 딕셔너리, 리스트, 튜플 계층 추가하지 말 것

  • 클래스로 기능 분리

    • 캡슐화 해주는 잘 정의딘 인터페이스 제공

    • 잘 정의된 추상화 계층 가능


클래스를 활용해 리팩토링하기

  • 의존관게 트리의 맨 밑바닥: 내포된 딕셔너리, 튜플, 리스트

  • 원소 세 개 이상인 튜플을 사용해야한다면, 다른 접근하기

    • from collections import namedtuple
  • namedtuple

    • 클래스의 인스턴스 만들 시 위치 기반 인자와 키워드 인자 사용

    • 필드에 접근 시, 애트리뷰트 이름 쓰기 가능

    • 요구사항이 바뀌어도 클래스로 변경이 쉽다.

    • 즉, 가변성을 지원한다.

from collections import namedtuple

Grade = namedtuple('Grade', ('score','weight')

namedtuple의 한계

  • 디폴트 인자 값을 지정할 수 없다.

  • 선택적 property가 많은 데이터 사용이 어려움

    • 만약 4~5개 이상이면 dataclasses 내장모듈 사용
  • API경우 실제 클래스 변경은 어렵다.

    • 명시적으로 새로운 클래스 정의가 편할 것이다.

#```
점수를 포함하는 단일 과목 표현하는 클래스 작성
class Subject:
def init(self):
self._grades = []

def report_grade(self, score, weight):
    self._grades.append(Grade(score, weight)

def average_grade(self):
    total, total_weight = 0.0
    for grade in self._grades:
        total += grade.score * grade.weight
        total_weight += grade.weight
    return total / total_weight

#수강하는 과목을 표현하는 클래스 작성

class Student:
def init(self):
self._subjects = defaultdict(Subject)

def get_subject(self, name):
    return self._subjects[name]

def average_grade(self):
    total, count = 0,0
    for subject in self._subjects.values():
        total += subject.average_grade()
        count += 1
    return total / count

#모든 학생을 저장하는 컨테이너를 만들어서 이름을 사용해서 동적으로 학생 저장

class Gradebook:
def init(self):
self._students = defaultdict(Student)

def get_student(self, name):
    return self._students[name]

#API를 사용중인 코드를 새로운 객체 계층을 사용하는 코드로 쉽게 마이크레이션 가능

book = Gradebook()
albert = book.get_student('알버트 아인슈타인')
math = albert.get_subject("수학")
math.report_grade(75,0.05)
math.report_grade(65,0.15)
math.report_grade(70,0.80)
gym = albert.get_subject('체육')
gym.report_grade(100,0,40)
gym.report_grade(85,0,60)
print(albert.average_grade()) #80.25

profile
성장을 도울 아카이빙 블로그

0개의 댓글