Done is Better Than Perfect

[Fluent Python 스터디] Study Note #1 Data Model 본문

공부/개발공부

[Fluent Python 스터디] Study Note #1 Data Model

jimingee 2021. 11. 15. 20:23

 

☢️ 파이썬으로 코딩테스트 공부를 할 만큼 파이썬에 익숙하지만 파이썬의 세계는 공부할수록 더욱 어려운 것 같다. 

 

☢️파이썬으로 학술 공부를 하려면 제대로 알아야 한다는 교수님의 추천과 파이썬스러움(pythonic)을 깊이있게 이해하고자

'Fluent Python' 스터디를 시작하였다. 

 


1-1. Python Data Model, Special Method

❌Abstract

파이썬이 처음 배울 때 좋은 언어라고 자주 언급되는 이유 중 하나는 언어의 일관성 때문이다. 

예를 들어, object의 경우 len( ) 함수를 사용하여 크기를 얻을 수 있다.

이와 일관되게, 사용자 정의 클래스는 __len__( )와 같은 특수 메서드를 구현할 때 이러한 기능을 사용할 수 있다.

 


💡 Python magic method

특별 메서드 = 매직 메서드(magic method) = dunder method (여기서 dunder는 double under의 줄임말)

 

👉앞 뒤에 이중 언더바 있음 [예, __getitem__( )

👉기본적인 언어 구조체 구현할 수 있음

👉특별 메서드는 파이썬 인터프리터를 호출하기 위한 것

파이썬 소스 코드에서는 object.__len__()으로 직접 호출 X  ➡️ len(object) 형태로 호출

👉종종 len( ), iter( ), str( ) 과 같은 파이썬 내장함수가 해당 특별 메서드를 호출

[파이썬 코드] for i in x  ➡️  iter(x) 호출 ➡️ [파이썬 인터프리터] x.__iter__( ) 호출

 

import collections

Student = collections.namedtuple('Student',['age', 'class_name'])

class Stud:
    age = [str(n) for n in range(10,15)]
    class_name = 'hana dol set net'.split()

    def __init__(self):
        self._std = [Student(age, class_name) for age in self.age 
        				for class_name in self.class_name]

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

    def __getitem__(self, position):
        return self._std[position]
        
 
friend = Stud()
print(len(friend))  #__len__( ) 함수를 파이썬 인터프리터에 전달
## 20

print(friend[0]) #__getitem__( ) 함수를 파이썬 인터프리터에 전달
## Student(age='10', class_name='hana')

print(friend[-1])
## Student(age='14', class_name='net')

print(friend[:3]) # list slicing 가능
## [Student(age='10', class_name='hana'), Student(age='10', class_name='dol'), Student(age='10', class_name='set')]

Stud 의 클래스에 __len__( ), __getitems__( )의 2개의 사용자 정의 특별 메서드를 구현하였다.

 

동작 구조 해석

➡️ len(friend) 함수는 __len__( ) 함수를 파이썬 인터프리터에 전달하였다. 

➡️ friend[0]은 __getitem__( ) 함수를 파이썬 인터프리터에 전달하였다. 

➡️ friend[:3]와 같이 list slicing 도 가능하다.

 


 

특별 메서드 구현의 의미
사용자 정의 객체도 내장형 객체처럼 작동  ➡️ 파이썬스러운(pythonic) 표현력있는 코딩 스타일 구사 가능

 


 

💡 Vector class

다음은 vector 클래스를 만들어 사용자 정의 특별 메서드를 만든 방식이다. 

 

from math import hypot

class Complicated:

    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __repr__(self):
        return 'Complicated num(%r + %ri)' % (self.x, self.y)

    def __abs__(self): # sqrt(x*x + y*y)
        return hypot(self.x, self.y)

    def __bool__(self): # complicated의 크기가 0이면 FALSE 반환, 아니면 TRUE 반환
        return bool(abs(self))

    def __add__(self, other):
        x = self.x + other.x
        y = self.y + other.y
        return Complicated(x, y)

    def __mul__(self, scalar):
        return Complicated(self.x * scalar, self.y * scalar)

c1 = Complicated(2,4) # __repr__() 호출
c2 = Complicated(2,1)
print(c1+c2) # __add__( ) 호출
## Complicated num(4 + 5i)

c = Complicated(3,4)
print(abs(c)) # __abs__( ) 호출
## 5.0

print(c*3) # __abs__( ) 호출
## Complicated num(9 + 12i)

print(abs(c*3)) #__mul__( ) 호출
## 15.0

 

👉 __repr__( ) __str__( ) 비교

 __str__( ) : print() 함수 포함됨 , 사용자에게 보여주기 적당한 형태의 문자열 반환

__repr__( ) : 반환한 문자열 명확

➡️ 둘 중 하나만 구현해야 한다면 __repr__( )을 구형하는 경우가 더 많다

 

Comments