Python

13. 파이썬의 객체지향과 클래스

muru_ 2024. 3. 18. 23:28

1. 객체지향 프로그래밍

- 객체지향 프로그래밍(Object-Oriented Programming, OOP)은 소프트웨어를 설계하고 구현하는 데 사용

- 프로그램을 '객체'라고 불리는 독립적인 개체로 나누고, 상호작용을 통해 프로그램을 구성하는 개발 방법론

2. 클래스

- 객체(Object) : 객체는 현실 세계에서의 실제 개체나 추상적인 개념을 모델링한 것입니다. 예를 들어, 자동차, 사람, 은행 계좌 등이 객체가 될 수 있습니다. 객체는 데이터(속성, 상태)와 메서드(동작, 함수)로 구성됩니다.

- 클래스(Class) : 클래스는 객체를 만들기 위한 템플릿 또는 설계도입니다. 클래스는 객체의 공통 속성과 동작을 정의하며, 객체를 생성하는데 사용됩니다. 예를 들어, "자동차" 클래스는 모든 자동차 객체가 가져야 하는 속성(색상, 속도)과 메서드(주행, 멈춤)를 정의할 수 있습니다.

- 인스턴스(Instance) : 클래스를 기반으로 실제로 생성된 객체를 인스턴스라고 합니다. 클래스는 여러 인스턴스를 생성할 수 있으며, 각 인스턴스는 독립적인 데이터와 메서드를 가집니다.

 

2-1. 클래스 만들기

# 기본형태
class 클래스이름:
    # 클래스 속성(멤버 변수) 정의
    속성1 = 초기값1
    속성2 = 초기값2

    # 생성자 메서드 (생략 가능)
    def __init__(self, 매개변수1, 매개변수2, ...):
        # 인스턴스 속성 초기화
        self.속성1 = 매개변수1
        self.속성2 = 매개변수2

    # 메서드(멤버 함수) 정의
    def 메서드1(self, 매개변수1, 매개변수2, ...):
        # 메서드 동작 정의
        pass

    def 메서드2(self, 매개변수1, 매개변수2, ...):
        # 메서드 동작 정의
        pass

# class만 모이는 쪽으로 메모리가 올라감
# class를 불러서 변수만 쓸 수 있음

 

2-2. 객체(인스턴스) 생성

class Dog:
    pass
    
Rucy = Dog()    # 메모리에 Rucy라는 변수가 생기고 Dog()이라는 객체를 가르키게 됨
print(Rucy)
print(type(Rucy))

PPomi = Dog()
print(PPomi)
print(type(PPomi))    # 같은 Dog()를 하나 더 만들어서 가르키게 됨

 

2-3. 객체 속성 초기화

class Dog:
    name = ''
    age = 0
    family = ''

Rucy = Dog()
print(Rucy.name)
print(Rucy.age)
print(Rucy.family)

Rucy.name = '루시'
Rucy.age = 14
Rucy.family = '포메'
print(Rucy.name)
print(Rucy.age)
print(Rucy.family)

PPomi = Dog()
PPomi.name = '뽀미'
PPomi.age = 7
PPomi.family = '폼피츠'
print(PPomi.name)
print(PPomi.age)
print(PPomi.family)

# class 는 붕어빵 틀
# 모양은 같지만 서로 다르게 만들어짐

 

2-4. 메서드의 사용

class Dog:
    name = ''
    age = 0
    family = ''

    def eat(self):      
        print('사료를 먹습니다.')
# 함수는 객체가 생길때마다 생기지 않고, 메모리에 하나만 생성되고 그 함수를 객체들이 공유함
# self는 메모리 주소를 전달하기 위해 씀. Rucy가 불렀냐 PPomi가 불렀냐의 구분
# (꼭 self로 안 적어도 됨)

Rucy = Dog()
Rucy.eat()

PPomi = Dog()
PPomi.eat()

 

3. 생성자

- 클래스의 인스턴스가 생성될  자동으로 호출되는 특별한 메서드

- 생성자는 객체의 초기화를 담당하며객체가 생성될  필요한 속성을 초기화하고 설정하는 역할

- 생성자 메서드는 __init__라고 이름이 정해져 있음

# 기본형태
class 클래스이름:
    def __init__(self, 매개변수1, 매개변수2):
        self.속성1 = 매개변수1
        self.속성2 = 매개변수2

 

# 만들면 자동호출, 만들지 않으면 내부적으로 빈 생성자를 만듬
class Dog:
    def __init__(self):
        print(self, 'init 호출!')
        
Rucy = Dog()

class Dog:
    def __init__(self):
        print(self, 'init 호출!')
        self.name = ''
        self.age = 0
        family = '포메'
        self.temp = family     # self를 붙여야 접근 가능

Rucy = Dog()
print(Rucy)
print(Rucy.name)
print(Rucy.age)
# print(Rucy.family)
print(Rucy.temp)

class Dog:
    def __init__(self, name, age, family='족보없음'):
        self.name = name
        self.age = age
        self.family = family

# 생성자에 전달할 파라미터(변수)
Rucy = Dog('루시', 14, '포메')    # '족보없음'은 안 쓰임
print(Rucy.name)
print(Rucy.age)
print(Rucy.family)

Pomi = Dog('포미', 5)    # family 기본값 '족보없음'
print(Pomi.name)
print(Pomi.age)
print(Pomi.family)

 

4. 메서드

- 클래스 내부에 정의되어 특정 객체에 연결된 함수

- 메서드는 해당 클래스의 모든 객체에서 공유되며객체의 동작을 정의하거나 특정 작업을 수행하는  사용

 

4-1. 메서드 정의

class Counter:
    # 생성자
    def __init__(self):
        self.num = 0
    # 메소드
    def increment(self):       # 번호 증가
        self.num += 1          # self를 붙였기 때문에 다른 함수에 있는 변수를1
                               # 가져다 쓸 수 있음

    def current_value(self):   # 현재 번호
        return self.num

    def decrement(self):       # 번호 감소
        self.num -= 1

    def reset(self):           # 0으로 초기화
        self.num = 0
        
KBbank = Counter()
print(KBbank.num)               # 0 
print(KBbank.current_value())   # 0

KBbank.increment()   # 손님이 세명 왔다
KBbank.increment()   
KBbank.increment() 
print(KBbank.num)    # 3
print(KBbank.current_value())  # 3

KBbank.decrement()   # 손님이 한명 빠졌다
print(KBbank.num)    # 2
print(KBbank.current_value()) # 2

# 메소드는 여러 방어코드를 넣을 수 있어서 값을 넣거나 뺄 때 
# 값(생성자)에다 직접 넣는 것이 아니라 메소드로 만들어서 처리하는 것이 좋다

HanaBank = Counter()
print(HanaBank.current_value())      # KBbank 와는 관련 없음
HanaBank.increment()
HanaBank.increment()
HanaBank.increment()
HanaBank.increment()
HanaBank.increment()
print(HanaBank.current_value())      # 5번 증가

HanaBank.reset()
print(HanaBank.current_value())     # 리셋 0

 

4-2. 메서드 타입

- 인스턴스 메서드(Instance Method) : 객체의 상태를 조작하거나 객체에 특정 작업을 수행하는 메서드, 대부분의 클래스 메서드는 인스턴스 메서드, 위의 예제에서 보여진 __init__ 메서드도 인스턴스 메서드.

 

- 클래스 메서드(Class Method) : 클래스 레벨에서 동작하며, 모든 인스턴스가 공유하는 메서드, 클래스 메서드 @classmethod 데코레이터를 사용하여 정의하며, 첫 번째 매개변수로 cls를 사용.

 

- 정적 메서드(Static Method) : 특정 클래스나 인스턴스와 관련이 없는 메서드로, 클래스 내부에 정의되어 있지만 클래스나 인스턴스와 독립적으로 호출될 수 있습니다. 정적 메서드는 @staticmethod 데코레이터를 사용하여 정의.

class Math:
    def add(self, x, y):
        return x + y
    def multiply(self, x, y):
        return x * y

math = Math()

result1 = math.add(10, 3)
print(result1)

result2 = math.multiply(10, 3)
print(result2)

# 굳이 객체로 만들어야 하나? 바로 함수로 쓰면 되지 않겠냐
# 함수는 타이틀이 없어서 개별적으로 외워야함

# 클래스 메서드
class Math:
    str1 = 'Hello! '
    @classmethod               # classmethod라고 불리는 메소드가 됨
    def add(cls, x, y):        # 함수로 기능하는 것뿐아니라 미리 제공되어있는 기능을 
        return x + y           # 전달받아서 변화가 일어남
                               # 바로 객체를 만들지 않아도 되는 메소드로 둔갑
        

    @classmethod
    def multiply(cls, x, y):
        return x * y

    @classmethod          # class 메모리(Math)와 함수 메모리(hello)가 따로 저장되어 있음
    def hello(cls, name):         # cls. <- 을 붙여주면 class 메모리 주소에 있는 
        return cls.str1 + name    # str1을 찾아감
        
print(Math.add(10, 3))           # math = Math() 할 필요가 없음
print(Math.multiply(10, 3))
print(Math.hello('김사과'))

# 정적 메서드
class Math:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    def add(self):
        return self.x + self.y

    def multiply(self):
        return self.x * self.y

    @staticmethod              # 같은 클래스에 있지만 add, multiply / subtract은
    def subtract(x, y):        # 서로 자료를 주고받을 수 없다
        return x * y           # 클래스에서 전혀 관련 없는 독립적인 메소드를 만들 때
                               # staticmethod를 쓴다
        
math = Math(10, 3)       # add 메소드와 multiply 메소드는 객체를 생성해야 쓸 수 있음

print(math.add())
print(math.multiply())

Math.subtract(10, 3)     # Math 클래스가 실행되는 동시에 subtract메소드가
                         # 따로 메모리에 올라감 (객체 생성 필요 없음)