Sign In

[Python] 클래스

Y
Yerim
  1. Python

클래스

클래스를 사용하는 이유

# calculator.py
result = 0

def add(num):
    global result
    result += num  # 결괏값(result)에 입력값(num) 더하기
    return result  # 결괏값 리턴

print(add(3))
print(add(4))
•
add함수에서 결과값을 유지하기 위해 전역변수를 사용
# calculator2.py
result1 = 0
result2 = 0

def add1(num):  # 계산기1
    global result1
    result1 += num
    return result1

def add2(num):  # 계산기2
    global result2
    result2 += num
    return result2

print(add1(3))
print(add1(4))
print(add2(3))
print(add2(7))
•
결괏값을 두 개 저장하기 위해서는 전역 변수가 하나 더 있어야 한다
•
계산기 1의 결과가 계산기 2에 영향을 미치지 않기 위해선 전역변수가 점점 더 늘어날 것이다
# calculator3.py
class Calculator:
    def __init__(self):
        self.result = 0

    def add(self, num):
        self.result += num
        return self.result

cal1 = Calculator()
cal2 = Calculator()

print(cal1.add(3))
print(cal1.add(4))
print(cal2.add(3))
print(cal2.add(7))
•
Calculator 클래스로 만든 별 개의 계산기는 각각의 역할을 독립적으로 수행한다
•
함수만 사용할 때보다 간단하게 프로그램을 작성할 수 있다

클래스와 객체

•
클래스 class: 똑같은 무언가를 계속만들어 낼 수 있는 설계 도면 (과자 틀)
•
객체 object: 클래스로 만든 피조물 (과자 틀로 찍어 낸 과자)
◦
동일한 클래스로 만든 객체들은 서로 영향을 미치지 않는다
◦
인스턴스 instance는 클래스로 만든 객체로 관계 위주로 설명할 때 사용한다

클래스 구조

def 함수_이름(매개변수):
    수행할_문장
    ...
class FourCal:
    base = 1
    def setdata(self, first, second): # 메서드의 매개변수
        self.first = first              # 메서드의 수행문
        self.second = second            # 메서드의 수행문
    def add(self):
        result = self.first + self.second
        return result
    def div(self):
        result = self.first / self.second
        return result

a = FourCal()            # 객체 생성
a.setdata(4, 2)          # first=4, seoncd=2
FourCal.setdata(b, 3, 7) # 메서드 호출 다른 방법
a.add() # 6
a.base # 1
•
구현된 함수는 메서드 method라고 한다
•
setdata 메서드는 self, first, second 3개의 입력값을 받는다
◦
self: 파이썬 메서드의 첫 번째 매개변수 이름은 관례적으로 self를 사용
◦
setdata(4, 2) → a.first=4 a.second = 2
•
서로 다른 객체인 a, b는 독립적이기 때문에 서로 영향을 미치지 않는
•
객체.메서드() 의 형태로 메서드를 실행할 수 있다
•
클래스_이름.클래스 변수로 클래스 변수를 사용할 수 있다
→ 객체의 클래스 변수 값을 바꿔도 클래스의 변수 값은 바뀌지 않음
•
self에는 객체 a가 자동으로 입력된다
생성자 constructor
class FourCal:
    def __init__(self, first, second):
        self.first = first
        self.second = second
    ...

a = FourCal(4, 2)
•
객체가 생성될 때 자동으로 호출되는 메서드를 의미
•
__init__를 사용하면 이 메서드는 생성자가 된다
•
위의 __init__ 메서드는 setdata 메서드와 동일하지만, 생성자로 인식되어 생성 시점에 자동으로 호출된다
예시
class Person:
    def __init__(self):
        self.name = input('이름')
        self.age = int(input('나이:'))
    def disp(self):
        print(self.name + ':' + self.age)

li = []
for i in range(3):
    li.append(Person())
for i in li:
    i.disp()

클래스 상속

class 클래스_이름(상속할_클래스_이름)
class MoreFourCal(FourCal):
    def __init__(self):
        super().__init__()
        self.third
    def pow(self):
        result = self.first ** self.second
        return result

a = MoreFourCal(4, 2, 5)
•
상속은 기존 클래스를 변경하지 않고 기능을 추가하거나 기존 기능을 변경할 때 사용
◦
self: 현재 객체, 인스턴스 변수가 메서드를 참조할 때 사용
◦
super(): 부모 클래스의 메서드를 호출할 때 사용, 부모 클래스의 __init__ 실행 시 유용
•
기존 클래스는 그대로 놔둔 채 클래스의 기능을 확장할 때 주로 사용
상속과 다형성
class Point:
    def __init__(self):
        self.x = int(input('x='))
        self.y = int(input('y='))
    def disp(self):
        pass

class Rect(Point):
    def __init__(self):
        super().__init__()
        self.w = int(input('w='))
        self.h = int(input('h='))
    def disp(self):
        print('사각형', self.x, self.y, self.w, self.h)

class Circle(Point):
    def __init__(self):
        super().__init__()
        self.r = int(input('r='))
    def disp(self):
        print('원', self.x, self.y, self.r)

def main():
    li = list()
    while True:
        s = input('1. 사각형, 2. 원, 3. 조회, 4. 종료:')
        if s == '1':
            li.append(React())
        if s == '2':
            li.append(Circle())
        if s == '3':
            for i in li:
                i.disp()
        if s == '4':
            break;
•
상속: 한 클래스가 다른 클래스의 속성과 메서드를 물려 받음 → 재사용성↑, 관계명
◦
Rect와 Circle 클래스는 Point 클래스를 상속받아 x, y 좌표를 상속
•
다형성: 하나의 메서드가 여러 형태로 동작
◦
파이썬에서는 주로 메서드 오버라이딩을 통해 다형성 구현
◦
disp() 메서드는 Point 클래스에서 정의되지 않고, 자식 클래스에서 다르게 구현

메서드 오버라이딩

class SafeFourCal(FourCal):
    def div(self):
        if self.second == 0: # 나누는 값이 0인 경우 0을 리턴
            return 0
        else:
            return self.first / self.second
•
div 메서드를 동일한 이름으로 다시 작성

접근 제한

class Sj:
    def __init__(self):
        self.kor
        self.__eng # 네임 맹글링 적용

obj = MyClass(90, 80)
print(obj.kor)      # 정상 출력
# print(obj.__eng)  # AttributeError
print(obj._Sj__eng) # 네임 맹글링된 이름으로 접근 가능
•
self.kor: 외부에서 자유롭게 접근하거 수정할 수 있는 일반적인 인스턴스 변수
•
self.__eng: 네임 맹글링을 통해 클래스 외부에서 직접 접근이 어려운 비공개 변수
◦
주로 외부에서 실수로 수정되지 않도로 보호하려는 목적
◦
변수의 이름을 변경하는 방식으로 접근을 어렵게 만든다

객체지향 프로그래밍 심화

클래스 메서드 (@classmethod)

•
클래스에 적용하는 메서드
•
첫 번째 인자로 클래스 자체를 받는다 (일반적으로 cls로 명명)
class MyClass:
    count = 0
    
    @classmethod
    def increment(cls):
        cls.count += 1

MyClass.increment()
print9MyClass.count) # 출력: 1

스태틱 메서드 (@staticmethod)

•
클래스나 인스턴스와는 독립적으로 작동하는 메서드
•
self나 cls와 같은 특별한 첫 번째 인자를 받지 않음
class MyClass:
    @staticmethod
    def my_method(x, y):
        return x + y

print(MyClass.my_method(5, 3)) # 출력: 8
class CompletionsList:
    def __init__(self):
        self.subject_list = []
    
    def show(self):
        print(self.subject_list)
    
    def append(Self, subject):
        self.subject_list.append(subject)
    
    @staticmethod
    def academic_warning(subject):
        '''
        내부에서 클래스 변수, 인스턴스 변수 수정하는 것이 가능하지 않습니다
        '''
        return abs(1.5 + subject['grades'])

c = CompletionList()

subject1 = {'name': 'Python', 'grades': 2.5}
subject2 = {'name': 'HTML/CSS', 'grades': 3.5}

c.append(subject1)
c.append(subject2)
c.show()

print(c.academic_warning(subject1))

속성 접근자 Property

•
@Property 데코레이터를 사용하여 클래스의 메서드를 속성처럼 접근할 수 있도록
•
객체의 내부 상태를 보호, 특정 속성에 대한 접근을 제어
class Person:
    def __init__(self first_name, last_name):
        self._first_name = first_name
        self._last_name = last_name
    
    @property
    def full_name(self):
        return f"{self._first_name} {self._last_name}"
    
hojun = Person("lee", "hojun")
hojun._first_name
hojun._last_name
hojun.full_name
hojun.full_name()
•
full_name 속성에 접근하면 _first_name과 _last_name을 합친 문자열을 반환
•
@property 데코레이터가 없다면 full_name() 메서드를 직접 호출해야한다
•
setter를 정의할 수도 있다 → 유효성 검사나 추가적인 연산 수행도 가능
Yerim-DevNote
Subscribe to 'Yerim-DevNote'
Subscribe to my site to be the first to receive notifications and emails about the latest updates, including new posts.
Join Slashpage and subscribe to 'Yerim-DevNote'!
Subscribe
👍