파이썬의 클래스 기반 접근 방식은 데이터와 동작을 단일 엔티티 내에 번들로 묶어 다양한 애플리케이션에서 코드를 재사용할 수 있는 우아한 솔루션을 제공합니다. 개발자는 개인이나 상품과 같은 실제 개체를 반영하는 사용자 정의 클래스를 구현함으로써 이러한 개체에 관련된 필수 속성과 기능을 효과적으로 캡처할 수 있습니다.

파이썬 클래스에는 사용자가 특정 시나리오에서 클래스의 동작을 수정하도록 맞춤 설정할 수 있는 “매직 메서드”라는 기능이 있습니다. 이 기능을 통해 개발자는 클래스에 개인화된 동작을 주입하여 코드 내에서 유연성과 적응성을 높일 수 있습니다.

매직 메서드 이해

흔히 던더 메서드라고 하는 매직 메서드는 엔티티에 대해 수행되는 특정 연산 중에 파이썬이 호출하는 수수께끼 같은 주문 또는 숨겨진 호출이라고 생각하면 됩니다.

인스턴스, 정적 변수, 클래스 메서드가 제공하는 기능을 활용하여 파이썬은 매직 메서드 구현을 통해 사용자 정의 가능한 기능을 갖춘 잘 구조화된 클래스를 개발할 수 있게 해줍니다.

파이썬에서 매직 메서드는 각 메서드 이름 앞뒤에 이중 밑줄 표기가 있는 인스턴스 메서드를 나타냅니다.

이러한 독특한 기법의 활용은 특정 클래스에 속하는 인스턴스 관리에 관한 지침을 파이썬에 제공합니다. 파이썬 클래스 내에서 가장 널리 사용되는 마법 메서드는 다음과 같습니다:

이 알고리즘은 지정된 객체의 값을 체계적으로 비교하여 지정된 객체가 지정된 다른 객체보다 수치적으로 큰지 여부를 확인합니다.

`__init__` 메서드는 클래스 인스턴스화 시 실행되며, 생성되는 객체의 속성을 초기화하는 것이 주요 목적입니다.

`__str__` 메서드는 해당 클래스의 인스턴스에 대한 텍스트 표현, 즉 “문자열”을 생성하는 역할을 담당합니다.

`__repr__` 메서드는 객체의 문자열 표현을 생성하는 역할을 하며, `eval()`에서 메모리에서 원래 객체를 재구성하는 데 사용할 수 있습니다.

`len()` 함수를 객체에 적용하면 객체의 크기 또는 범위의 측정값을 산출합니다.

`__eq__` 메서드를 사용하면 이중 등호(`==`) 연산자를 사용하여 개체 간에 비교할 수 있습니다.

__lt__ 클래스는 관련 클래스의 인스턴스에 대해 보다 작음(<>) 비교 연산을 구현할 책임이 있습니다.

두 개 이상의 객체를 추가하는 프로세스는 `+` 연산자에 의해 촉진되며, 이 연산자는 객체에 적용될 때 덧셈 연산을 실행합니다.

`__getitem__` 메커니즘을 사용하면 `obj[key]`와 같은 인덱스 표기법을 사용하여 엔티티 내의 객체를 검색할 수 있습니다.

이 글도 확인해 보세요:  슬랙에서 나만의 사용자 지정 슬래시 명령 만들기

매직 메서드 구현하기

매직 기법을 실제로 사용함으로써 매직 기법에 대한 포괄적인 이해를 얻을 수 있습니다.

객체의 문자열 표현

주어진 객체의 이해도를 높이고 후속 조작을 용이하게 하기 위해 객체의 형식화된 표시를 조정할 수 있습니다.

 class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = Person('John', 25)
print(p1)

본 인스턴스화는 초기화 목적으로 ‘**init**’ 메타메서드를 통합하는 Person 클래스의 초보적인 반복을 포함합니다. ‘p1’로 표시되는 지각을 렌더링할 때 파이썬 프로그래밍 언어가 제공하는 고유한 문자열 표현을 활용합니다.

Python에서 객체의 표시를 개인화하는 한 가지 방법은 특수 메서드 `__str__` 및 `__repr__`을 구현하는 것입니다. 이 메서드를 사용하면 객체가 문자열로 표시되거나 `print()`를 사용하여 인쇄될 때 표시되는 방식을 제어할 수 있습니다. 이러한 메서드를 정의하면 코드에서 생성되는 출력을 더 세밀하게 제어할 수 있습니다.

 class Person:
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height

    def __str__(self):
        return f'{self.name} is {self.age} years old'

    def __repr__(self):
        return f'{self.name} is {self.age} years old'

p1 = Person('John', 25, 78)
print(p1)

실제로 `p1` 객체의 수정된 문자열 표현은 읽기 쉽고 내용을 포괄합니다.

객체의 길이 속성

`Person` 클래스에서 `__len__` 매직 메서드의 구현은 다음과 같습니다: “python def __len__(self): RETURN SELF._HEIGHT

 class Person:
    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height

    def __str__(self):
        return f'{self.name} is {self.age} years old'

    def __repr__(self):
        return f'{self.name} is {self.age} years old'

    def __len__(self):
        return self.height

p2 = Person('Issac', 25, 89)
print(len(p2))

`__len__` 매직 메서드는 객체에서 내장된 `len()` 함수가 호출될 때 호출되며, 컨테이너에 있는 객체 수를 반환합니다. 이 경우 `len(p2)` 표현식이 평가되면 Python은 `p2`와 연결된 `Person` 클래스의 `__len__` 메서드를 호출하여 사람의 이름 목록의 길이(즉, 키)를 반환합니다.

객체 간 비교 처리

특정 클래스에 속한 인스턴스의 동등성을 해당 클래스 내에 내재된 특정 속성에 따라 평가하기 위해서는 `__eq__` 마법 메서드를 도입하고 기본 비교 근거를 구현해야 합니다.

 class Person:

    def __init__(self, name, age, height):
        self.name = name
        self.age = age
        self.height = height

    def __str__(self):
        return f'{self.name} is {self.age} years old'

    def __repr__(self):
        return f'{self.name} is {self.age} years old'

    def __len__(self):
        return self.height

    def __eq__(self, other):
        return self.name == other.name and self.age == other.age

p1 = Person('John', 25, 56)
p2 = Person('John', 25, 61)

print(p1 == p2)

`__eq__` 메서드는 `Person` 클래스의 두 인스턴스의 `name` 및 `age` 속성을 비교하여 동등성을 판단하는 역할을 담당합니다.

이 글도 확인해 보세요:  Reqwest로 Rust에서 HTTP 요청 만들기

파이썬에서 “==”로 표시되는 이중 등호 기호는 동일성 비교를 평가하는 대신 특정 접근 방식을 사용하여 동등성을 결정합니다. 따라서 ‘Person’ 클래스의 인스턴스와 함께 사용하면 각각의 이름과 나이 속성을 비교하여 동등성을 판단합니다. 이렇게 하면 사용자 지정 클래스의 객체가 동등성을 평가하는 표준 방식을 수정할 수 있습니다.

이러한 매혹적인 기법을 활용하면 파이썬의 기본 기능의 고유한 속성에 따라 고유한 특성을 설정할 수 있습니다.

고급 마법 방법

다양한 마법 기법을 통해 클래스를 개인화하는 데 인챈트가 어떻게 활용될 수 있는지 살펴봅니다.

클래스가 컨테이너처럼 작동하게 만들기

아케인 기술을 활용하여 컨테이너의 속성을 구현하는 클래스를 만들 수 있습니다. 튜플과 같은 이러한 리셉터클은 데이터 구성 요소의 집합을 저장할 수 있습니다. 둘러싸인 엔티티의 조작, 검색 및 탐색을 수행하기 위한 수많은 신비한 주문이 존재합니다.

 class Person:
    def __init__(self):
        self.data = []

    def __len__(self):
        return len(self.data)

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

    def __delitem__(self, index):
        del self.data[index]

p1 = Person()
p1.data = [10, 2, 7]
print(len(p1)) # 3

p1[0] = 5
print(p1[0]) # 5

이제 사람은 정보나 물건을 담거나 저장하는 능력과 관련된 행동 속성을 통해 수용체의 특성을 나타낼 수 있습니다.

속성 액세스 사용자 지정

`__getattr__` 마법 절차를 사용하여 특정 기준에 따라 `사람` 클래스의 속성을 검색하는 방식을 맞춤 설정할 수 있습니다.

 class Person:
    def __getattr__(self, name):
        if name == 'age':
            return 40
        else:
            raise AttributeError(f'No attribute {name}')

p1 = Person()
print(p1.age) # 40

`__getattr__` 메서드를 사용하여 객체에 존재하지 않는 속성에 액세스하려고 하면 요청된 속성의 이름이 “age”인지 여부를 실행하여 확인합니다. 그렇다면 40이라는 값을 반환합니다.

지정된 사전에 존재하지 않는 속성에 액세스하거나 조작하려는 시도가 있는 경우 프로그램은 `AttributeError` 예외를 throw합니다. 이 오류에는 액세스하려고 했지만 찾을 수 없는 속성을 나타내는 설명 메시지가 포함됩니다.

클래스를 콜러블처럼 동작하게 만들기

`__call__` 메서드를 사용하면 클래스의 인스턴스화를 기능적으로 가능한 엔티티로 인식할 수 있으므로 표준 콜러블 구조체와 유사한 방식으로 호출할 수 있습니다.

 class Adder:
    def __call__(self, x, y):
        return x + y

adder = Adder()
print(adder(2, 3)) # 5

Adder 객체의 인스턴스화는 인수를 사용하여 호출될 때 해당 __call__ 메서드를 트리거하고, 이후 더하기 연산을 실행하고 결과 합계를 미리 반환합니다.

이 글도 확인해 보세요:  JES를 활용한 흥미로운 사운드 처리 기법 3가지

연산자 오버로드

파이썬의 연산자 오버로드를 사용하면 개발자가 각 클래스의 인스턴스에 적용할 때 내장된 연산자의 동작을 재정의하여 사용자 정의 객체에 새로운 의미와 기능을 부여할 수 있습니다. 이 개념의 대표적인 예로 2차원 공간에서 점을 나타내는 클래스를 들 수 있는데, 이 클래스에는 오버로드된 산술 연산자가 벡터 덧셈과 뺄셈을 비롯한 여러 연산을 효율적으로 계산할 수 있게 해줍니다.

 class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        if isinstance(other, Vector):
            new_x = self.x + other.x
            new_y = self.y + other.y
            return Vector(new_x, new_y)
        else:
            raise TypeError("Unsupported operand type for +")

    def __str__(self):
        return f"({self.x}, {self.y})"

# Creating two Vector instances
v1 = Vector(2, 3)
v2 = Vector(1, 4)

# Adding two Vector instances using the + operator
v3 = v1 + v2

# Printing the result
print(v3) # Output: (3, 7)

결과는 새로운 벡터,

`Vector` 클래스는 클래스의 두 인스턴스에 덧셈 연산자(+)가 적용될 때마다 호출되는 `__add__()` 메서드에 대한 구현을 제공합니다. 이 메서드는 두 벡터에서 해당 요소의 합을 계산하고 결과 값을 포함하는 새 `Vector` 객체를 생성합니다.

여기서는 클래스 동작을 사용자 정의하기 위해 구현할 수 있는 기본적인 매직 메서드를 살펴봤습니다. 파이썬에는 클래스를 만들 때 더 많은 유연성을 제공하는 더 많은 매직 메서드가 있습니다. 전체 목록은 공식 문서 를 참조하세요.

파이썬의 객체 지향 프로그래밍

파이썬 내에서 매직 메서드를 활용하면 객체 지향 프로그래밍(OOP)의 원칙에 따라 클래스의 기능을 조정하고 증폭할 수 있는 강력한 수단을 제공합니다. 따라서 이 마법 같은 메서드의 기능을 활용하기 위해서는 OOP의 원리를 이해하는 것이 무엇보다 중요합니다.

By 박준영

업계에서 7년간 경력을 쌓은 숙련된 iOS 개발자인 박준영님은 원활하고 매끄러운 사용자 경험을 만드는 데 전념하고 있습니다. 애플(Apple) 생태계에 능숙한 준영님은 획기적인 솔루션을 통해 지속적으로 기술 혁신의 한계를 뛰어넘고 있습니다. 소프트웨어 엔지니어링에 대한 탄탄한 지식과 세심한 접근 방식은 독자에게 실용적이면서도 세련된 콘텐츠를 제공하는 데 기여합니다.