IT world

[Python] 24.01.10 클래스 본문

모두의 연구소(오름캠프)/AI 모델 활용 백엔드 개발 과정

[Python] 24.01.10 클래스

엄킹 2024. 1. 10. 17:36

1. 클래스(Class)

클래스란?

데이터(멤버 또는 애트리뷰트(속성), 변수)와 기능(메서드, 함수)을 갖는 데이터 타입. 이를 통해 만들어진 것을 인스턴스 객체라고 한다.

 

파이썬은 객체지향 프로그래밍 언어로 class를 기반으로 객체를 생성한다. 즉 string, list, float, dictionary와 같은 것들이 모두 클래스로 존재한다는 것이다.

 

* 객체지향 프로그래밍(Object-Oriented Programming, OOP)이란..

프로그래밍에 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만들고, 그 객체들 간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법.

 

많은 객체들이 모여 상호 협력하면서 데이터를 처리하는 방식 또는 프로그램을 묶음 단위로 잘게 쪼개서 추후에 가져다 쓰기 편하게 만들어 놓은 프로그래밍 방식이라고 보면 된다.

[객체지향 그림 예시]

 

* 객체(Object)란..

그렇다면 객체란? 클래스로 생성되어 구체화된 것이 객체이다. 클래스에서 정의한 것을 토대로 실제 메모리에 할당된 것을 객체라 하는데 파이썬의 모든 것들을 객체라고 생각하면 되지 않을까 싶다..

 

다시 돌아와서, 클래스(Class)는 쉽게 말해 객체(instance)를 만들어내기 위한 틀로 생각하면 된다. 

더 쉽게 말해 붕어빵을 만들기 위해 필요한 틀을 클래스라 생각하고, 생산품인 붕어빵을 객체로 생각하면 될 것 같다.

 

이렇게 동일한 무언가를 계속해서 만들어낼 수 있는 형태이며 만들어낸 객체들은 모두 고유한 성격을 가진다.

클래스를 왜 써야하는가?

1. 속도

클래스는 구조적으로 설계할 수 있는 구조이다. 사용하는 변수외 메서드를 최소화하여 메모리를 최적화할 수 있고, 구조적으로 빠른 속도를 실현하게 구현할 수 있다.

 

2. 재사용성

한번 클래스를 작성하면 여러 객체를 만들 수 있다. 

# Class 기본 구조

class Character: # 클래스명은 대문자를 권함
	
    # 클래스 변수 선언
    name = '홍길동' 
    age = 20
    
    # 함수 선언
    def __init__(self):
    	self.power = 100
    
    def add_age(self, age):
    	self.age = age

 

# 인스턴스를 만든다.

hero = Character()
print(hero.power)

 

클래스를 생성하여 인스턴스를 만들어 보았다. 이때 생성된 객체는 dot(.)을 이용해 클래스의 멤버와 메서드에 접근할 수 있다.

 

__init__ 함수와 self

  • __init__함수

위의 코드를 보면 __init__ 함수와 self 키워드를 확인할 수 있다. 

사용자는 hero라는 객체를 만들때 power 변수에 대한 값을 설정하지도,  __init__ 함수를 호출하지 않았음에도 hero.power를 호출하면 100이 출력된다.

 

init은 initialize를 줄인 말로, 뜻 그대로 처음에 초기화를 시켜준다는 의미이다.

따라서 객체를 생성할때 특정 값으로 속성을 초기화시켜주고 싶다면 __init__함수를 이용한다.

 

__init__ 메서드는 클래스를 통해 객체를 생성하는 순간에 가장 먼저 호출되는 특별한 메서드이다. 흔히 클래스의 '생성자'라고 한다. 즉 인스턴스가 생성될 때 가장 처음 실행되는 매직 메서드이다. 

# Class 기본 구조

class Character: # 클래스명은 대문자를 권함
	
    # 클래스 변수 선언
    name = '홍길동' 
    
    # 함수 선언
    def __init__(self, name, age):
    	self.name = name # 재할당
        self.age = age
        
hero = Character('홍길동', 10)
print(hero.name)

# 출력 : 홍길동

 

이처럼 Character라는 클래스를 생성할 때 가장 먼저 __init__함수가 호출되고 hero의 객체의 name에 값을 할당한다.

 

  • self

self는 해당 메소드가 호출하는 객체 자기자신을 가리킨다. 반드시 self일 필요는 없지만 관례적으로 self를 사용한다.

self 매개변수에는 메서드를 호출한 객체 hero가 자동으로 전달되기 때문에 2개의 인자만 전달한다

"항상 첫번째 매개변수인 self에는 자기자신이 들어간다"

또한 위 코드를 확인하면 age라는 변수는 클래스에 존재하지 않는다. 하지만 self를 통해 age라는 매개변수의 값을 소유할 수 있게 되는 것이다. 

 

클래스 변수

클래스 변수는 클래스 바로 하위에 자리하고 있으며 클래스 변수는 해당 클래스를 통해 만들어진 모든 인스턴스 객체들이 공유하는 변수다.

class Car:
    # 클래스 변수의 위치
    max_speed = 300
    max_people = 5
    car_gear = ['P', 'D', 'R', 'N']

 

인스턴스 변수

인스턴스 변수는 self가 위치한 어디서나 선언이 가능하지만 보통 __init__ 메서드 안에서 선언된다.

dot으로도 호출하여 변경할 수 있으며 다른 인스턴스와 메모리 영역을 공유하지 않는다. 

class Car:
    max_speed = 300

    def __init__(self, name): # self는 자신만의 영역
        self.name = name

    def start(self, speed): # self는 자신만의 영역
        self.speed = speed

modelx = Car('Tesla Model X')
modelx.name = 'ModelY'

 

* 인스턴스 객체가 모두 공통으로 공유하는 값이 클래스 변수라면, 인스턴스 변수는 각 인스턴스 객체가 가지고 있는 값으로 인스턴스 내부에서만 사용이 가능하다.

 

class Car:
    # 클래스 변수의 위치
    max_speed = 300

modelx = Car()
modely = Car()

modely.max_speed = 500 # modely의 speed 값만 변경

print(modelx.max_speed)
print(modely.max_speed)

 

위와 같이 작성하면 modely의 max_speed는 500이 되고, 클래스 변수는 모든 변수가 공유하는 변수라고 하였으니 modelx의 값도 바뀌어야할 것 같지만 modely의 max_speed값을 조정하는 것은 modely의 인스턴스 변수의 값을 변경하는 것과 같다.

class Car:
    kinds = []
    speed = 300

    def add_kinds(self, name):
        self.kinds.append(name)

    def change_speed(self, speed):
        self.speed = speed

modelx = Car()
modely = Car()

modelx.add_kinds('x')
modely.add_kinds('y')

Car.speed = 100

# modelx.change_speed(500)
# modely.change_speed(250)

print(f'modelx.kinds: {modelx.kinds}')
print(f'modely.kinds: {modely.kinds}')
print(f'modelx.speed: {modelx.speed}')
print(f'modely.speed: {modely.speed}')

 

modelx와 modely 인스턴스를 생성하였고, 인스턴스 영역 내 self.kinds 변경이 없으므로 class 영역에서 해당 변수를 찾아 값을 추가하게 된다. 이는 하나의 메모리 영역을 공유하고 있다는 것을 말해준다.

(self.kinds = [] 시 공유하지 않는다.)

 

또한 Car.speed = 100의 코드를 보면 클래스에 직접 접근하여 클래스 변수를 수정하였으므로 두 객체 값 모두 변경된 것을 확인할 수 있다.

 

2. 예외처리

2.1 Error의 종류

  • 문법 에러 (Syntax Error)
  • 이름 에러 (Name Error)
  • 타입 에러 (Type Error)
  • 인덱스 에러 (Index Error)
  • 키 에러 (Key Error)
  • 값 에러 (ValueError)
  • 제로 나누기 에러 (ZeroDivisionError)
  • 어트리뷰터 에러 (Attribute Error)
  • 인자 개수 에러 (TypeError)
  • 파일 입출력 에러 (File I/O Error)

2.2 예외 처리 방법

  • try-except
  • try-except-else : else 에러가 발생하지 않으면 호출
  • try-finally : finally → 마지막에 무조건 호출
  • try-except-finally
  • try-except-else-finally
  • assert

[예외처리 예시]

 

Comments