APIView 내부 코드를 이해하기 위한 Python 문법

서재환·2022년 8월 29일
0

Django

목록 보기
19/40

💡 학습목표

APIView 내부 코드를 이해하기 위해 Python 문법 알기

💡 선행개념

  • 상속
  • 명령행 인자
  • 데코레이터
  • 프로퍼티

상속

  • 부모 클래스의 속성과 메서드를 자식이 물려받는 것을 의미한다.
  • 상속 방법은 아래와 같다.
class Parent():
	"""Super Class"""
	...

class Child(Parent):
	"""Sub Class"""
	...
  • 오버라이딩
    - 메소드 오버라이딩은 부모 클래스의 메소드를 자식 클래스에서 재정의 하는 것입니다.

  • 파이썬은 메소드 오버로딩이 없다.
    - Java의 경우 하나의 클래스 내 동일한 이름의 여러 메서드를 사용할 수 있지만(인자를 다르게 가져감으로써) 파이썬의 경우 마지막에 작성한 함수가 그 전에 함수를 덮어쓰는 형태로 작동하게 된다.

  • super()
    - 키워드이고 해당 키워드를 통해 자식 클래스에서 부모의 속성과 메서드에 접근할 수 있다.

  • @staticmethod
    - 자식 클래스의 인스턴스 객체에서 부모 클래스에 선언된 staticmethod를 호출할 수 있고 부모클래스의 변수 및 메서드를 호출할 수 있다. classmethod 와의 차이는 staticmethod는 인자로 cls가 없다. 해당 형태로 인해 차이점이 발생한다.

  • @classmethod
    - staticmethod와의 차이는 인자로 cls를 받는다는 점이다. 이 하나의 차이로 인해 두 메서드 간의 차이가 발생한다. 자식 클래스의 인스턴스에서 부모 클래스의 변수 및 메서드에 접근할 수 있다. 여기서 자식 인스턴스로 부모 클래스 메서드에 접근하게 됐을 때 cls의 인자로 자기 자신이 넘어가는 로직이 staticmethod와는 다른점이다.

명령행 인자

함수가 인자를 받을 때 파라미터 순으로: [일반 변수, *변수, **변수] 순으로 받아야 한다.

  • *변수는 여러개가 들어올 때 함수 내부에서 변수를 튜풀로 처리한다.
  • **변수는 여러개가 들어올 때 각각을 키와 값으로 처리한다.

데코레이터

데코레이터는 자신이 실행 할 함수 앞 또는 뒤로 무엇을 실행해주고 싶을 때 사용한다. 장식(decorate)해준다. 예를 들어 올림픽 개막식과 폐막식이 올림픽이라는 행사를 꾸며주는 요소라고 보면 이를 데코레이터로 인식하는 것이다.

파이썬에서는 함수 기반과 클래스 기반이 있는데 함수 기반부터 살펴보자

def decorator(func):
	def sub_decorator():
    	print('개막식')
        func()
        print('폐막식')
    return sub_decorator

위 함수를 보면 1.함수를 인자로 받는다. 2.함수 안에는 함수가 있고 3.그 함수를 결과값으로 반환한다. sub_decorator()만 실행시켰을 때에는 1.개막식이 출력되고 2.인자로 받은 함수가 실행되고 3.마지막으로 폐막식이 출력된다. 이런 일련의 과정을 인자로 들어오는 함수 별로 다르게 하고 싶을 때 데코레이터가 빛을 발휘한다.

그럼 장식해보자

@decorator
def func_1():
	print('func1')

@decorator
def func_2()
	print('func 2')

장식물을 붙이는 방법은 장식할 대상 함수에 @함수이름을 기입하면 된다.

이번에는 class를 통해 작성하는 방법을 알아보자

class Decorator:
	def _init_(self, func):
		self.func = func
    
    def _call_(self, *args, **kwargs):
    	print('개막식')
        func(*args, **kwargs)
        print('폐막식')

class Main:
	
    @Decorator
	def func_1():
    	print('func1')
        
    @Decorator
    def func_2():
    	print('func2')

main = Main()
main.func_1()
main.func_2()

프로퍼티

선행 개념

  • getter
  • setter
  • descriptor

프로퍼티가 탄생한 이유는 인스턴스 생성시 인스턴스의 속성에 직접 접근하는 것을 방지하기 위해서이다. 그래서 해당 속성 값을 보호하기 위해 getter() 메서드와 setter() 메서드를 통해 값을 가지고 오거나 값을 변경하는 방법을 주로 사용하고있다.

매번 속성에 접근할 때 getter()와 setter() 메서드를 호출하는 것은 번거롭기 때문에 @property가 탄생하였다.

@property 구문이 의미하는 바는 메서드를 실행한다는 것이다.
Person.num -> Person 인스턴스의 num 메서드를 실행하겠다는 의미이다.

class Person:
    def __init__(self, number):
        self.__number = number
    
    @property
    def num(self):
        return self.__number
    
    @num.setter
    def num(self, number):
        self.__number = number

p = Person(10)

print(p.num) #10

디스크립터

파이썬에서 하나의 객체(A)는 다른 객체(B)를 속성으로 가질 수 있습니다. 이때 속성이 되는 그 객체(B)의 값을 읽거나 쓰거나 삭제할 수 있는데 이 때 객체(B)를 디스크립터라고 합니다. 디스크립터 내부 메서드 get, set, del 중 하나만 있어도 디스크립터에 해당한다.

예제를 통해 이해해보겠습니다.

class CharacterInfo:
    def __init__(self, power, speed):
        self.power = power
        self.speed = speed

    def __get__(self, obj, objtype):
        print('(GET)정보 조회됨')
        return ("공격력 : "+str(self.power) + " / 스피드 : " + self.speed)

    def __set__(self, obj, val):
        print('(UPDATE)정보 갱신 시작')
        self.power = val.power
        self.speed = val.speed

    def __delete__(self, obj):
        print("(DELETE)정보 삭제하기")
        self.power =""
        self.speed = ""


class Guardian:
    info = CharacterInfo(10, "50km/h")


g1 = Guardian()   # g1 이라는 수호천사 인스턴스 하나 생성
print(g1.info)   # 인스턴스 g1의 초기 정보 출력 
info_after_upgrade = CharacterInfo(15, "70km/h")   # 업그레이드 아이템 적용 후 캐릭터 정보
g1.info = info_after_upgrade   # 새 캐릭터 정보를 인스턴스 g1 에 설정
print(g1.info)   # 인스턴스 g1의 정보 출력
del g1.info   # 인스턴스 g1의 정보 삭제
print(g1.info)   # 인스턴스 g1의 정보 출력
def __get__(self, obj, objtype):
	print('(GET)정보 조회됨')
    return ("공격력 : "+str(self.power) + " / 스피드 : " + self.speed)

g1 = Guardian()
가디언의 인스턴스 g1이 만들어졌을 때 g1은 CharacterInfo의 인스턴스 info를 속성으로 갖습니다.

g1.info로 디스크립터 info에 접근하게 되면 CharacterInfo 내부 get method를 실행시킨다.

내부 get method는 인자로 (self, obj, objtype)을 갖는데 각각의 정체는 다음과 같다.

  • self: CharacterInfo의 인스턴스, 즉 디스크립터
  • obj: Guardian의 인스턴스, 디스크립터를 속성으로 갖고 있는 인스턴스
  • Guardian의 타입
def __set__(self, obj, val):
        print('(UPDATE)정보 갱신 시작')
        self.power = val.power
        self.speed = val.speed

set의 경우 objtype 대신 val 이라는 인자를 갖는데 새로 생성한 인스턴스에 해당한다. 여기선 CharaterInfo의 인스턴스이다.

직렬화

직렬화에 대해서 알아보자. 네트워크를 통해 데이터를 전달할 때 해당 데이터의 형태는 연속된 바이트의 흐름이다. 그 전에 데이터의 형태는 구조체 형태를 띤다. 따라서 구조체 형태의 데이터를 연속된 바이트의 형태로 바꿔 주어야 한다. 이를 직렬화라고 한다.

직렬화
추상적인 object를 구체적이고, 저장 가능하고, 전송 가능한 텍스트 파일로 바꿔주는 것

역직렬화
텍스트 파일을 직렬화된 데이터 포맷 형태로 추상적인 object 데이터로 구조체로 바꿔주는 것

선행 조건

  • 데이터를 직렬화하고 역직렬화 하려면, 데이터 포맷을 알고 있어야 한다. JSON, XML, YAML과 같은 문서 포맷이 주로 직렬화의 대상이 된다.

0개의 댓글