Python의 마법 방법 I

2024. 4. 7. 15:59python/advanced

 

 

python의 마법 방법:Classes에서 그 힘을 활용하세요

 

객체 지향 프로그래밍의 강력한 기능을 활용하려는 Python 개발자라면 매직 메서드 또는 던더 메서드 라고도 하는 특수 메서드를 사용하여 클래스를 사용자 정의하는 방법을 배우고 싶을 것입니다 . 특수 메소드는 이름이 이중 밑줄로 시작하고 끝나는 메소드입니다. 이러한 메서드는 Python에서 특별한 의미를 갖습니다. Python은 인스턴스화, 시퀀스 인덱싱, 속성 관리 등과 같은 특정 작업에 대한 응답으로 매직 메서드를 자동으로 호출합니다. 매직 메서드는 Python의 핵심 객체 지향 기능을 지원하므로 이에 대해 배우는 것은 Python 프로그래머로서 기본입니다.

이 튜토리얼에서는 다음을 수행합니다.

  • Python의 특수 메서드나 마법 메서드가 무엇 인지 알아보세요.
  • Python의 매직 메소드 뒤에 숨어 있는 마법을 이해하세요
  • 특별한 메소드를 사용하여 사용자 정의 클래스의 다양한 동작을 사용자 정의하세요.

이 튜토리얼을 최대한 활용하려면 일반적인 Python 프로그래밍에 익숙해야 합니다. 더 중요한 것은 Python의 객체 지향 프로그래밍과 클래스의 기본 사항을 알아야 한다는 것입니다 .

 

Python의 마법이나 특별한 방법 알아보기

 

Python에서는 특수 메소드를 매직 메소드 또는 던더 메소드 라고도 합니다. 후자의 용어인 dunder는 Python이 특별한 메소드 와 속성 의 이름을 지정하는 데 사용하는 특정 명명 규칙을 나타냅니다 . 관례는 현재 이름에 이중 선행 및 후행 밑줄을 사용하는 것이므로 .__method__() 같게 보입니다. 참고: 이 튜토리얼에서는 특수 메서드 , 던더 메서드 , 매직 메서드라는 용어가 같은 의미로 사용되는 것을 볼 수 있습니다.

이중 밑줄은 이러한 메서드를 일부 Python 기능의 핵심으로 표시합니다. 이는 고유한 메소드 및 속성과의 이름 충돌을 방지하는 데 도움이 됩니다. 널리 알려져 있고 잘 알려진 몇 가지 매직 방법은 다음과 같습니다.

특별한 방법 설명
.__init__() Python 클래스에서 초기화 프로그램을 제공합니다.
.__str__() 그리고 .__repr__() 객체에 대한 문자열 표현 제공
.__call__() 클래스의 인스턴스를 호출 가능하게 만듭니다.
.__len__() len()기능을 지원합니다.

이것은 Python이 가지고 있는 모든 특수 메소드의 작은 샘플일 뿐입니다. 이러한 모든 방법은 Python과 객체 지향 인프라의 핵심인 특정 기능을 지원합니다. Python 문서에서 특수 메서드 라는 용어를 정의하는 방법은 다음과 같습니다 . 추가와 같은 유형에 대한 특정 작업을 실행하기 위해 Python에서 암시적으로 호출되는 메서드입니다. 이러한 메서드에는 이중 밑줄로 시작하고 끝나는 이름이 있습니다. ( 원천 ) 이 정의에는 강조해야 할 중요한 세부 사항이 있습니다. Python은 코드에서 특정 작업을 실행하기 위해 암시적으로 특수 메서드를 호출합니다 . 예를 들어 REPL5 + 2 세션 에서 추가를 실행하면 Python은 내부적으로 다음 코드를 실행합니다.

 
(5).__add__(2)
 
 
 

.__add__() 정수의 특별한 방법은 일반적으로 5 + 2으로 실행되는 덧셈을 지원 합니다.

줄 사이를 읽어보면 특수 메서드를 직접 호출할 수 있더라도 직접 사용하기 위한 것이 아니라는 점을 알게 될 것입니다. 코드에서 직접 호출하면 안 됩니다. 대신 Python을 사용하여 주어진 작업에 대한 응답으로 자동으로 호출해야 합니다.

참고: 특수 메서드를 매직 메서드 라고도 하지만 Python 커뮤니티의 일부 사람들은 이 후자의 용어를 좋아하지 않을 수 있습니다. 이러한 메서드와 관련된 유일한 마법은 Python이 내부적으로 이를 암시적으로 호출한다는 것입니다. 따라서 공식 문서에서는 대신 이를 특수 메서드 라고 부릅니다 .

매직 메소드는 다양한 목적으로 존재합니다. 사용 가능한 모든 매직 메서드는 내장 기능을 지원하고 언어에서 특정 역할을 수행합니다. 예를 들어 목록 , 문자열 및 사전 과 같은 내장 유형은 매직 메소드를 사용하여 대부분의 핵심 기능을 구현합니다. 사용자 정의 클래스에서는 매직 메서드를 사용하여 호출 가능한 개체를 만들고, 개체를 비교하는 방법을 정의하고, 개체를 만드는 방법을 조정할 수 있습니다.

매직 메서드는 Python 자체에 특별한 의미가 있으므로 선행 및 후행 이중 밑줄을 사용하여 사용자 정의 메서드 이름을 지정하지 않아야 합니다. 사용자 정의 메서드는 이름이 공식적인 특수 메서드 이름과 일치하지 않으면 Python 작업을 트리거하지 않지만 확실히 다른 프로그래머를 혼란스럽게 할 것입니다. 새로운 던더 이름은 Python의 향후 버전에도 도입될 수 있습니다. 매직 메소드는 Python 데이터 모델 의 핵심 이며 Python의 객체 지향 프로그래밍의 기본 부분입니다. 다음 섹션에서는 가장 일반적으로 사용되는 특수 메서드 중 일부에 대해 알아봅니다. 일상적인 프로그래밍 모험에서 더 나은 객체 지향 코드를 작성하는 데 도움이 될 것입니다.

 

객체 생성 프로세스 제어

 

Python에서 사용자 정의 클래스를 생성할 때 구현하는 첫 번째이자 가장 일반적인 메서드는 아마도 .__init__() 일 것입니다. 이 메서드를 사용하면 클래스에서 정의하는 모든 인스턴스 속성 에 초기 값을 제공할 수 있으므로 초기화 프로그램 으로 작동합니다. 특수 .__new__() 메소드는 클래스 인스턴스화 프로세스에서도 역할을 합니다. 이 메서드는 클래스 생성자를 호출할 때 지정된 클래스의 새 인스턴스를 생성하는 작업을 처리합니다. 하지만 이 .__new__() 메소드는 실제로는 덜 일반적으로 구현됩니다. 다음 섹션에서는 이 두 메서드의 작동 방식과 이를 사용하여 클래스 인스턴스화를 사용자 지정하는 방법에 대한 기본 사항을 알아봅니다.

 

객체 초기화.__init__()

 
Selection deleted
Python은 주어진 클래스의 생성자를 호출할 때마다 .\_\_init\_\_() 메서드를 호출합니다. .\_\_init\_\_()의 목표는 클래스에 있는 모든 인스턴스 속성을 초기화하는 것입니다. 다음 Point 클래스를 고려해보세요:
 
Selection deleted
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
 
point = Point(21, 42)
 
point.x
 
 
 
point.y
 
 
 

Point() 클래스 생성자를 호출하여 point 인스턴스를 생성하면, Python은 생성자에 전달한 것과 동일한 인수를 사용하여 내부적으로 자동적으로 .__init__()을 호출합니다.  직접 .__init__() 호출하실 필요는 없습니다. 단지 Python의 암시적 동작에 의존할 뿐입니다. 생성자를 호출할 때 전달하는 값이 .x및 .y 속성에 어떻게  저장되는지 확인하세요.

 

.__new_`_()을 사용하여 개체 만들기

 

클래스 생성자를 호출하여 클래스의 새 인스턴스를 생성하면 Python은 인스턴스화 프로세스의 첫 번째 단계로 .__new__() 메서드를 암시적으로 호출합니다. 이 메소드는 기본 클래스의 새로운 빈 객체를 생성하고 반환하는 일을 담당합니다. 그런 다음 Python은 초기화를 위해 방금 생성된 객체를 .__init__()에 전달합니다 . .__new__()의 실제 사용 사례에는 기본 구현만으로 충분합니다. 따라서 대부분의 경우 .__new__()를 사용자 정의 구현을 작성할 필요가 없을 것입니다 . 그러나 일부 고급 사용 사례에서는 이 방법이 유용하다는 것을 알게 될 것입니다. 예를 들어 int, float, tuple및 str그리고 float 와 같은 불변 유형의 하위 클래스를 만드는 데 .__new__() 를 사용할 수 있습니다 . 내장 데이터 유형에서 상속되는 클래스의 다음 예를 고려하십시오.

 
Selection deleted
class Storage(float):
def __new__(cls, value, unit):
instance = super().__new__(cls, value)
instance.unit = unit
return instance
 
 
 

이 예에서는 .__new__()가 현재 인스턴스(self)가 아닌 현재 클래스(cls)를 인수로 가져오기 때문에 .__new__()가 클래스 메서드 라는 점을 알 수 있습니다. 그런 다음 세 단계를 실행합니다. 먼저, 내장 super() 함수를 통해 float 클래스 위에 .__new__()를 호출 하여 현재 클래스의 새 인스턴스 cls를 만듭니다. 이 호출은 float의 새 인스턴스를 생성 하고 인수로서 value를 사용하여 초기화합니다.

그런 다음 .unit 속성을 동적으로 연결하여 새 인스턴스를 사용자 정의합니다. 마지막으로 .__new__()의 기본 동작을 충족하기 위해 새 인스턴스를 반환합니다.

이 클래스가 실제로 작동하는 방식은 다음과 같습니다.

 
disk = Storage(1024, "GB")
 
disk
 
 
 
disk.unit
 
 
 
isinstance(disk, float)
 
 
 

Storage 클래스가 예상대로 작동하므로 인스턴스 속성을 사용하여 저장 공간을 측정하는 단위를 저장할 수 있습니다. .unit 속성은 변경 가능하므로 언제든지 해당 값을 변경할 수 있습니다. 그러나 disk의 숫자 값은 상위 유형인 float처럼 변경할 수 없기 때문에 변경할 수 없습니다.

 

객체를 문자열로 표현하기

 

Python 코드에서 수행하는 일반적인 작업은 데이터를 표시하거나 출력을 생성하는 것입니다. 어떤 경우에는 프로그램이 사용자에게 유용한 정보를 표시해야 할 수도 있습니다. 다른 경우에는 코드를 사용하여 다른 프로그래머에게 정보를 표시해야 할 수도 있습니다.

이 두 가지 유형의 출력은 각각의 대상 고객이 서로 다른 요구를 가질 수 있기 때문에 상당히 다를 수 있습니다. 사용자를 위한 정보는 구현 세부 사항을 강조할 필요가 없을 수도 있습니다. 사용자 친화적이고 명확해야 할 수도 있습니다.

대조적으로, 프로그래머 청중을 위한 정보는 코드 구현에 대한 세부 사항을 제공하면서 기술적으로 타당해야 할 수도 있습니다.

Python에서는 두 가지 시나리오를 모두 다루었습니다. 사용자에게 친숙한 출력을 제공하려면 이 .__str__()함수를 사용할 수 있습니다. 반면, 개발자 친화적인 출력을 제공해야 하는 경우 .__repr__() 메서드를 사용할 수 있습니다. 이러한 메서드는 Python 객체에 대해 두 가지 다른 문자열 표현을 지원합니다.

 

.__init__()와 함께 .__str__() 및 .__repr__() 메서드는 사용자 정의 클래스에서 가장 일반적으로 사용되는 특수 메서드입니다. 다음 섹션에서는 이러한 두 가지 유용한 방법에 대해 알아봅니다.

 

사용자 친화적인 문자열 표현.__str__()

 

.__str__() 특수 메소드는 현재 객체에 대해 사람이 읽을 수 있는 문자열 표현을 반환합니다. Python은 내장 str()함수를 호출할 때 이 메서드를 호출하여 클래스의 인스턴스를 인수로 전달합니다.

Python은 인스턴스를 print() 및 format() 함수에 대한 인수로 사용할 때도 이 메서드를 호출합니다. 이 메서드는 애플리케이션의 최종 사용자가 이해할 수 있는 문자열을 제공하기 위한 것입니다.

.__str__() 메서드를 사용하는 방법을 설명하려면 다음 Person 클래스를 고려하세요.

 

<주의> 아래 코드를 person.py로 저장하세요.

 
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
 
def __str__(self):
return f"I'm {self.name}, and I'm {self.age} years old."
 
 
 

이 클래스에는 사람의 이름과 나이라는 두 가지 속성이 있습니다. .__str__() 메서드에서는 사람에 대한 사용자 친화적인 문자열 표현을 반환합니다. 이 표현에는 설명 메시지에 이름과 나이가 포함됩니다.

다음은 수업 진행 방식의 예입니다.

 
Selection deleted
from person import Person
 
jane = Person("Jane Doe", 25)
 
str(jane)
 
 
 
print(jane)
 
 
 

Person의 인스턴스를 str() 혹은 print()에 대한 인수로 사용하면 화면에 개체의 문자열 표현이 표시됩니다. 이 표현은 애플리케이션이나 코드 사용자를 위해 특별히 제작되었습니다.

 

개발자 친화적인 문자열 표현 .__repr__()

 

.__repr__() 메서드는 개발자를 대상으로 하는 개체의 문자열 표현을 반환합니다. 이상적으로, 반환된 문자열은 문자열에서 개체의 동일한 인스턴스를 구성할 수 있는 방식으로 제작되어야 합니다.

.__repr__() 동작 방식을 자세히 알아보려면, Person 클래스로 돌아가서 아래 코드 조각과 같이 업데이트하세요.

 

.__repr__()에서는 f-문자열을 사용하여 객체의 문자열 표현을 만듭니다. 이 표현의 첫 번째 부분은 클래스 이름입니다. 그런 다음 한 쌍의 괄호를 사용하여 생성자의 인수와 해당 값을 래핑합니다.

이제 REPL 세션을 다시 시작하고 다음 코드를 실행하세요.

 

<주의) jupyter notebook에서 kernek을 재 시작해 주세요.

 
Selection deleted
from person import Person
 
john = Person("John Doe", 35)
 
john
 
 
 
repr(john)
 
 
 

이 예에서는 Person의 인스턴스를 만듭니다. 그런 다음 REPL을 통해 인스턴스에 직접 액세스합니다. 표준 REPL은 자동으로 메서드를 사용하여 .__repr__() 개체에 대한 즉각적인 피드백을 표시합니다.

마지막 예에서는 인수로 전달한 개체에서 .repr()를 호출하는 내장 repr() 함수를 사용합니다.

결과 문자열 표현을 따옴표 없이 복사하고 붙여넣어 현재 개체를 재현할 수 있습니다. 이 문자열 표현은 귀하의 코드를 사용하는 다른 개발자에게 매우 편리합니다. 이 표현으로부터 현재 객체가 어떻게 구성되는지에 대한 중요한 정보를 얻을 수 있습니다.

 

'python > advanced' 카테고리의 다른 글

Python의 마법 방법 VI  (0) 2024.04.12
Python의 마법 방법 V  (0) 2024.04.11
Python의 마법 방법 IV  (0) 2024.04.11
Python의 마법 방법 III  (0) 2024.04.09
Python의 마법 방법 II  (0) 2024.04.08