python에는 특수한 메소드가 있다
magic method라고 하는 것인데 함수의 이름 앞뒤에 언더스코어(_)가 두 개씩 붙어있는 것이다
class를 만들때 처음에 생성자같은 역할을 하는 __init__함수를 정의하는데 이것이 매직 메소드이다.
문자열 연산시 연산자가 오버로딩 되는 것처럼
이 형태의 함수가 파이썬에서 미리 정의되어있고, 사용자가 재정의(오버로딩, overloading)함으로써 사용할 수 있는 것이다.
class Student :
def __init__(self, name, dept, number, grade) :
self.stu_name = name
self.stu_dept = dept
self.stu_number = number
self.stu_grade = grade
stu1 = Student('소크라테스', '철학과', '201101', 3.5)
print(stu1)
지난번의 사용했던 코드이다. Student클래스 안에 __init__말고 다른 메소드가 없다.
이때 이 코드를 실행해보면
stu1 인스턴스의 주소가 출력된다.
<__main__.Student object at 0x0000012C9457C5B0>
__str__이라는 이름의 메소드가 주소값을 리턴하도록 정의 되어있기 때문이다.
이제 위의 코드에 __str__을 재정의해서 이름을 리턴하도록 만들어보면 다음과 같다.
class Student :
def __init__(self, name, dept, number, grade) :
self.stu_name = name
self.stu_dept = dept
self.stu_number = number
self.stu_grade = grade
def __str__(self) :
return 'My name is {}'.format(self.stu_name)
stu1 = Student('소크라테스', '철학과', '201101', 3.5)
print(stu1)
이 코드의 실행결과는 다음과 같다!
My name is 소크라테스
Student 클래스가 가지는 함수의 목록을 보기위해 다음 코드를 실행해보면
print(dir(Student))
이렇게나 많은 함수가 존재하는 것을 알 수 있다. 내가 정의한 것은 2개 밖에 없는데도 말이다!
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__',
'__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
이 함수들의 역할이나 매직메소드를 더 알아보려면
공식문서를 참고하면 된다
3. 데이터 모델 — Python 3.7.12 문서
클래스는 특별한 이름의 메서드들을 정의함으로써 특별한 문법 (산술 연산이나 인덱싱이나 슬라이딩 같은)에 의해 시작되는 어떤 연산들을 구현할 수 있습니다. 이것이 연산자 오버 로딩 (operato
docs.python.org
활용)
위의 예에서 매직메소드 오버로딩을 활용해서 할 수 있는 예시를 하나 생각해보았다.
만약 학생의 학점(grade)가 4.0이상인지 알아보기 위해서는
매직메소드를 이용하지 않으면 다음과 같이 작성해야한다.
print(stu1.stu_grade >= 4.0) ##False
물론 간단한 예시이기 때문에 크게 불편하지는 않다.
하지만 인스턴스 변수에 직접 접근하는 것은 좋은 방법도 아닐 뿐더러,
코드가 복잡해지면 작성하기 어려워질 것이다.
is_over_four라던지 따로 함수를 정의해서 비교할 수도 있지만
print(stu1.is_over_four())
매직메소드를 이용하면 훨씬 간단해진다!
class Student :
def __init__(self, name, dept, number, grade) :
self.stu_name = name
self.stu_dept = dept
self.stu_number = number
self.stu_grade = grade
def __str__(self) :
return 'My name is {}'.format(self.stu_name)
def __ge__(self, require):
return self.stu_grade >= require
__ge__는 >=를 사용할 때 호출되는 함수이다.
Student와 float는 비교할 수 없는 대상이지만 __ge__를 재정의하여 비교할 수 있게 만들었다.
object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)
These are the so-called “rich comparison” methods. The correspondence between operator symbols and method names is as follows:
x<y calls x.__lt__(y),
x<=y calls x.__le__(y),
x==y calls x.__eq__(y),
x!=y calls x.__ne__(y),
x>y calls x.__gt__(y),
and x>=y calls x.__ge__(y).
print(stu1>=4.0)
[재정의 전 결과]
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-60-5f09d5ee027c> in <module>
----> 1 print(stu1>=4.0)
TypeError: '>=' not supported between instances of 'Student' and 'float'
[재정의 후 결과]
False
'Programming > Python' 카테고리의 다른 글
[Python] 이터레이터 계속 반복하기 itertools cycle (0) | 2022.07.06 |
---|---|
[python] 환경변수 설정과 모듈만들기 (1) | 2022.01.26 |
[python] 함수 (0) | 2022.01.21 |
[python] 제어문 Control Statement (0) | 2022.01.20 |
[Python]Data type 2 - Sequence, Text Sequence, Mapping, Set, Bool (0) | 2022.01.20 |