카테고리 없음

재귀함수와 클래스 심화 추상클래스 serializer

끈끈 2023. 4. 26. 23:25

 

재귀의 이해

 

재귀함수

스스로를 호출하는 함수

 

 

DFS(깊이 우선 탐색) BFS(너비 우선 탐색)
현재 정점에서 갈 수 있는 점들까지 들어가면서 탐색
경로의 특징을 가진다
현재 정점에 연결된 가까운 점들부터 탐색
스택 또는 재귀함수로 구현 를 이용해서 구현

 

 

return 값이 없는 재귀함수

def recursion(n):
	if n < 5:
    recursion(n + 1)
    
recursion(1)
# 1
# 2
# 3
# 4

 

return 값이 있는 재귀함수

def recursion(n):
	if n <= 0:
    	return 0
    return n + recursion(n - 1)
    
print(recursion(4)) # 10

 

 

모든 재귀함수는 반복문으로 구현이 가능하다

 

>>> 코드가 훨씬 짧기 때문에 재귀함수 사용

 

종료 조건이 중요하다

 

>>> 끝도 없이 호출되서는 안 됨. 언젠가는 실행이 멈춰야 함

RecursionError: maximum recursion depth exceeded while calling a Python object

 

 

최대 재귀 깊이(maximum recursion depth)

 

재귀함수를 최대로 호출할 수 있는 횟수 파악

print(sys.getrecursionlimit())

 

재귀 문제 유형

1. 문제 푸는 전체 과정을 펼쳐 생각해 보았을 때

>>> 문제 풀이 과정의 일부분이 문제를 푸는 전체 과정과 유사함

 

2. 문제 풀이 과정에서 비슷한 논리가 꼬리에 꼬리를 무는 형태로 이루어져 있음

 


 

팩토리얼(!)

어떤 수보다 작거나 같은 모든 양의 정수를 곱한 값

 

def factorial(n):
    if n == 0:
        return 1
    return n * factorial(n-1)


print(factorial(16))

 

피보나치 수열

첫째 항이 0, 둘째 항이 1
그 뒤의 모든 항은 바로 앞 두 항의 합인 수열

 

def fibo(n):
    if n == 1:
        return 0
    elif n == 2:
        return 1
    return fibo(n-1) + fibo(n-2)


print(fibo(12)) # 89

 

 

과제

파스칼의 삼각형(Pascal's triangle)

8번째 줄을 리스트로 출력하는 함수 만들기

1. 첫번째 줄에는 1을 쓴다
2. n번째 줄(n >= 2) 줄을 만들 때 n-1번째 줄의 왼쪽 숫자와 오른쪽 숫자를 더한다
    n-1번째 줄의 왼쪽 숫아 혹은 오른쪽 숫자 중 하나가 없을 경우 존재하는 수만 더한다

 

def pas(n):
    if n == 1:
        return [1]
    else:
        return [1] + [(pas(n-1)[i])+(pas(n-1)[i+1]) for i in range(n-2)] + [1]


print(pas(8))  # [1, 7, 21, 35, 35, 21, 7, 1]

 

파스칼의 삼각형

 


 

클래스 심화

 

메서드 오버라이딩(Method Overriding)

 

파생 클래스에서 상위 클래스의 메서드를 재정의하는 것

 

이름은 같지만 다른 기능을 수행하도록 재정의

 

1. 모델 클래스 메서드 오버라이딩

from django.db import models

class MyModel(models.Model):
	name = models.CharField(max_length=100)
    
    # save 메서드를 오버라이딩하여 저장하기 전 특정 작업 수행
    def save(self, *args, **kwargs):    	
        self.name = self.name.upper() # name 속성의 값을 대문자로 변환
        super(MyModel, self).save(*args, **kwargs) # 저장

 

2. 폼 클래스 메서드 오버라이딩

from django.db import forms

class MyForm(forms.Form):
	name = forms.CharField(max_length=100)
    
    # clean_name 메서드를 오버라이딩하여 입력값을 검증하거나 처리하는 등의 작업 수행
    def clean_name(self):    	
        name = self.clean_data['name']
        return name.capitalize() # name 필드 값의 첫 글자를 대문자로 변환

 

3. 뷰 함수 메서드 오버라이딩

from django.views.generic import TemplateView

class MyView(TemplateView):
	template_name = 'my_template.html'
    
    # dispatch 메서드를 오버라이딩
    def dispatch(self, request, *args, **kwargs):
    	# 요청 처리 전 특정 작업 수행
        result = super(MyView, self).dispatch(request, *args, **kwargs)
        # 요청 처리 후 특정 작업 수행
        return result

 

추상 클래스(Abstract Class)

  • 상속하여 하위 클래스에서 구현해야 하는 클래스
  • 상속받는 클래스에서 반드시 구현해야 함
  • 인터페이스만 정의해 줌
  • 인스턴스를 생성할 수 없는 클래스

 

 


 

serializer를 사용하는 이유

  1. 직렬화
  2. 데이터 검증

 

serializer의 validate

필드의 유효성 검사 → 커스텀 validate

 

is_valid

serializer.is_valid(raise_exception=True)
serializer.save()


def save(self, **kwargs):
  pass

 

raise_exception=True를 통해 is_valid 체크에서 에러가 나면

 

ValidationError를 raise 하여 HTTP 400 Bad Request 응답을 리턴

 

  • self.instance 값이 있을 때 : update()를 통해서 저장
  • self.instance 값이 없을 때 : create()를 통해서 저장

 

def crate(self, validated_data)
    password = validated_data.pop("password")
    user = User(**validated_data)
    user.set_password(password)
    user.save()

 


 

다음 주 예고

  • 다형성
  • 데코레이터 (DRF View)