Python/Python 기초

[Python] 클래스 ( class )

죵욜이 2024. 12. 1. 13:27

클래스( class ) 란?

객체 지향 프로그래밍 의 기본적인 구성 요소로, 객체를 생성하고, 객체의 속성과 동작을 관리할 수 있다.

 

쉽게말해 객체를 만들기 위한 설계도 라고 생각하면 된다.

class 클래스이름:
    # 클래스 변수
    클래스변수 = 값

    # 생성자 메서드 (매직 메서드)
    def __init__(self, 인자1, 인자2):
        self.인스턴스변수1 = 인자1
        self.인스턴스변수2 = 인자2

    # 일반 메서드
    def 메서드이름(self, 인자):
        # 동작 정의
        return 값

 

더보기
class Person:
    # 클래스 변수
    species = "Human"

    # 생성자
    def __init__(self, name, age):
        self.name = name  # 인스턴스 변수
        self.age = age

    # 메서드
    def greet(self):
        return f"Hello, my name is {self.name} and I am {self.age} years old."

# 객체 생성
person1 = Person("Alice", 25)
person2 = Person("Bob", 30)

# 객체 사용
print(person1.greet())  # Hello, my name is Alice and I am 25 years old.
print(person2.greet())  # Hello, my name is Bob and I am 30 years old.

# 클래스 변수 접근
print(Person.species)  # Human
print(person1.species) # Human
  • 클래스 이름은 대문자로 시작하고 PascalCase(각 단어의 첫글자는 대문자, 밑줄_ 사용하지않기) 가 권장

주요 개념

1. 생성자 ( __init__ )

  • 객체가 생성될 때 자동으로 호출되는 메서드
  • 객체의 초기값을 설정
def __init__(self, name, age):
    self.name = name
    self.age = age

 

2. 인스턴스 변수와 클래스 변수

  • 인스턴스 변수 : 개별 객체마다 독립적으로 존재하며  self  를 통해 접근
  • 클래스 변수 : 클래스 자체에 속하며 모든 객체가 공유

 

3. 메서드

  • 클래스 내부에 정의된 함수로, 객체의 동작을 정의
  • 일반적으로 첫 번째 매개변수로  self  를 사용해 객체 자신을 참조

 

4. 상속

  • 한 클래스가 다른 클래스의 속성과 메서드를 물려받는 것.
class ParentClass:
    # 부모 클래스의 내용

class ChildClass(ParentClass):
    # 자식 클래스의 내용 (부모 클래스의 속성과 메서드를 상속받음)

 

더보기
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "소리를 냅니다."

class Dog(Animal):  # Animal 클래스를 상속받아 Dog 클래스 정의
    def speak(self):  # 부모 클래스의 메서드를 재정의 (오버라이딩)
        return f"{self.name}가 멍멍 짖습니다."

# 객체 생성
dog = Dog("Buddy")
print(dog.speak())  # Buddy가 멍멍 짖습니다.

 

5. 캡슐화

  • 변수나 메서드를  또는  __  로 시작해 접근제한을 설정할 수 있다.
  •  _  : 암묵적 보호 (protected)
  •  __  : 강력한 보호 (private)
class Example:
    def __init__(self):
        self.public_var = "public"
        self._protected_var = "protected"
        self.__private_var = "private"

obj = Example()
print(obj.public_var)  # public
print(obj._protected_var)  # protected
print(obj.__private_var)  # AttributeError: 'Example' object has no attribute '__private_var'

 


추가 개념

 

매직 메서드

  • 클래스의 특정 동작을 정의하기 위해 미리 정해진 이름의 메서드
  •  __이름__   형태로 구성되며, 파이썬 내부적으로 특정 상황에서 자동 호출
더보기

1. 객체 초기화( __init__ ) 및 소멸( __del__ )

 __init__(self, ...) 

  • 객체의 초기화 작업을 수행
  • 객체가 생성될 때 호출
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p = Person("Alice", 25)  # __init__ 호출

 

 __del__(self) 

  • 주로 정리작업 (리소스 해제 등) 에 사용
  • 객체가 소멸될 때 호출
class Resource:
    def __del__(self):
        print("Resource released")

r = Resource()
del r  # __del__ 호출

2. 문자열 표현

 __str__(self) 

  • print() 나 str() 함수가 호출될 때 실행
  • 사용자 친화적인 문자열을 반환
class Person:
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return f"My name is {self.name}"

p = Person("Alice")
print(p)  # My name is Alice

 

 __repr__(self) 

  • 주로 디버깅에 사용
  • 객체의 공식적인 문자열 표현을 반환
class Person:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return f"Person(name='{self.name}')"

p = Person("Alice")
print(repr(p))  # Person(name='Alice')

3. 연산자 오버라이딩

 __add__(self, other) 

  •  +  연산자를 정의
class Number:
    def __init__(self, value):
        self.value = value
    def __add__(self, other):
        return Number(self.value + other.value)

a = Number(10)
b = Number(20)
c = a + b  # __add__ 호출
print(c.value)  # 30
  • 기타 연산자 
연산자 메서드이름
- __sub__(self, other)
* __mul__(self, other)
/ __truediv__(self, other)
// __floordiv__(self, other)
% __mod__(self, other)
** __pow__(self, other)

 


4. 비교연산자

 __eq__(self, other) 

  •  ==  연산자를 정의
  • 기타 비교연산자
연산자 메서드이름
!= __ne__(self, other)
< __lt__(self, other)
<= __le__(self, other)
> __gt__(self, other)
>= __ge__(self, other)

 


5. 컨테이너 동작

 __len__(self) 

  • 객체의 길이를 반환
  • len() 함수 호출시 사용
class MyList:
    def __init__(self, items):
        self.items = items
    def __len__(self):
        return len(self.items)

my_list = MyList([1, 2, 3])
print(len(my_list))  # 3

 

 __getitem__(self, key) 

  • 객체가 인덱싱 될때 호출
class MyList:
    def __init__(self, items):
        self.items = items
    def __getitem__(self, index):
        return self.items[index]

my_list = MyList([1, 2, 3])
print(my_list[1])  # 2

 

 __setitem__(self, key, value) 

  • 객체에 값을 할당할 때 호출

 __delitem__(self, key) 

  • 객체에서 값을 삭제할 때 호출

클래스 메서드 ( @classmethod  )

  • 클래스 자체를 첫 번째 인자로 받음  ( cls )
  • 데코레이터 사용 ->  @classmethod  를 사용해 정의
  • 클래스 변수 접근 가능
  • 클래스의 상태를 변경 가능
class MyClass:
    class_variable = "Hello"

    @classmethod
    def change_class_variable(cls, value):
        cls.class_variable = value

    @classmethod
    def show_class_variable(cls):
        print(f"Class variable: {cls.class_variable}")


# 클래스 메서드 호출
MyClass.show_class_variable()  # Class variable: Hello
MyClass.change_class_variable("Hi")
MyClass.show_class_variable()  # Class variable: Hi

 


정적 메서드 ( @staticmethod )

클래스와 관련이 있지만, 클래스나 인스턴스의 상태를 변경하거나 접근할 필요가 없는 기능을 구현할 때 사용

  • 클래스나 인스턴스와 무관 -> 첫 번째 인자로  self  나  cls  를 받지않음
  • 데코레이터 사용 ->  @staticmethod  를 사용해 정의
  • 클래스 안에 있지만 일반 함수처럼 동작
class MyClass:
    @staticmethod
    def add_numbers(a, b):
        return a + b

    @staticmethod
    def greet(name):
        print(f"Hello, {name}!")


# 정적 메서드 호출
print(MyClass.add_numbers(10, 20))  # 30
MyClass.greet("Alice")  # Hello, Alice!

상속 - 심화 

 super() 

  • 자식 클래스에서 부모 클래스의 메서드나 속성을 호출할 때 사용
class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # 부모 클래스의 __init__ 호출
        self.breed = breed

    def describe(self):
        return f"{self.name} is a {self.breed}"

dog = Dog("Buddy", "Golden Retriever")
print(dog.describe())  # Buddy is a Golden Retriever

추상 클래스

  • 직접 인스턴스를 생성할 수 없는 클래스
  • 주로 다른 클래스가 상속받아 사용할 수 있도록 설계된 템플릿 역할을 한다.
  •  abc  모듈(추상 기반 클래스, Abstract Base Classes) 을 사용해 정의

 

 @abstractmethod 

추상클래스를 구성하는 메서드를 정의하는 데 사용된다.

추상메서드는 구현되지 않은 메서드로, 반드시 서브클래스에서 구현해야 한다.

 

특징

 

  • 강제성 부여:
    • 자식 클래스에서 특정 메서드들을 반드시 구현하도록 강제합니다.
  • 구현 없이 선언만 가능:
    • 메서드의 이름과 인터페이스만 정의하고, 실제 구현은 서브클래스에서 담당합니다.
  • 추상 클래스와 함께 사용:
    • 추상 메서드는 추상 클래스 안에서만 정의됩니다.
  • 직접 인스턴스화 불가:
    • 추상 메서드가 있는 클래스를 직접 인스턴스화하려고 하면 오류가 발생합니다.

 

from abc import ABC, abstractmethod

# 추상 클래스 정의
class Animal(ABC):
    @abstractmethod
    def speak(self):
        pass

    @abstractmethod
    def move(self):
        pass

# 자식 클래스
class Dog(Animal):
    def speak(self):
        return "Woof!"

    def move(self):
        return "Runs on four legs"

# 인스턴스 생성
dog = Dog()
print(dog.speak())  # Woof!
print(dog.move())   # Runs on four legs

# Animal 클래스는 직접 인스턴스화 불가
try:
    animal = Animal()
except TypeError as e:
    print(e)  # "Can't instantiate abstract class Animal with abstract methods move, speak"