본문 바로가기
Python/개념

Day 6-2. 콜백함수와 람다함수

by 사라리24 2024. 3. 15.
SMALL

 

 

더보기

들어가기 전에 ...

'람다함수'는 파이썬에만 존재하는 특수언어라고 할 수 있습니다. 특별한 함수를 여러번 실행할 때 사용되는 함수입니다.
다른 사람들의 코드를 이해하기 위해  알아야 할 필요성이 있습니다.

'콜백함수'는 다른 언어에도 쓰이는 기본 언어입니다. 모르면 파이썬을 이용할 때 문제가 될 수 있습니다.
이해가 필수입니다.

함수는 자주 쓰는 것들을 블록으로 묶어서 메모리에 올려놓고 다음 작업 때 이름만 불러서 사용할 수 있게 합니다.
함수는 메모리에 올라가 있다는 것을 알고 있고 이름으로 호출할 수 있습니다.
매개변수나 리턴값을 사용해서 확장성있게 할 수 있습니다. 

함수를 실행할 때 기본적으로 func1( ) 라고 입력합니다.
그러나 함수를 다른 쪽에 실행하지 않고 저장할 수 있습니다. temp = func1
그러면 temp도 메모리를 알고 있기에 temp( )로 실행할 수 있습니다. 결과는   func( )과 같습니다.

함수도 메모리에 저장되어 있는 객체임으로 변수도 주고받고 할 수 있습니다.
줬을 때 다른 변수가 받아서 언제든지 다른 이름을 실행할 수 있습니다.

 

 

1. 콜백함수(callback function)

콜백 함수는 다른 함수에 인자로 전달되어, 어떤 이벤트나 특정 조건에서 실행되게 되는 함수를 말합니다.
콜백 함수는 주로 비동기 작업이나 특정 이벤트 발생 시점에 어떤 동작을 수행할 때 사용됩니다.

 

 

더보기

비동기 작업이란?

- 동기식: 아무리 시간이 걸려도 순서대로 위에서 아래로 내려가는 것
- 비동기식: 순서가 없이  속도가 빠른 것들을 먼저 처리하는 것

인터넷을 통해서 DB를 받아와서 화면에서 처리해야 하는데  메모리가 적게 드는 것을 우선적으로 실행해 띄우고 
나머지는 나중에 띄우도록 하는 작업

 (예) 카카오톡 화면에 사람정보와 메세지가 나열되어야 때 
방법1) 다 받아올 때까지 로딩바를 띄운다.
방법2) 메모리가 작은 메세지를 채운뒤 메모리가 큰 프사는 나중에 받아와서 채운다.

(예) for문을 10억바퀴를 돌린다면 출력은 기다리고 있는 상태
방법1) 처리가 빨리 된 것부터 출력한다.

- 이벤트 기반 프로그래밍: 많은 이벤트 기반 프로그래밍 환경에서는 이벤트 발생 시점에 콜백 함수를 실행하여 사용자에게 알리거나 특정 동작을 수행합니다.

- 비동기 작업: 특히 비동기 처리를 할 때, 작업의 완료나 실패 시점에 콜백 함수를 실행하여 결과를 반환하거나 오류를 처리합니다.

(* 비동기 작업: 위->아래로 순차적으로가 아니라 속도가 빠른 것들 먼저 순서가 없이 처리하는 것)

- 코드의 유연성: 콜백 함수를 사용하면 함수나 클래스의 코드를 변경하지 않고도 동작을 확장하거나 수정할 수 있습니다.

 

 
  def callback_func(func):
      for i in range(5):
          func( )

  def print_hello( ):
      print('안녕하세요! 파이썬!')

  print_hello( )
 
  # 콜백을 이용하는 이유
 
   - 함수를 다른 함수에게 매개변수로 전달하고 싶음
   - 그 함수를 원하는 만큼 실행 하고 싶을 때 
 
안녕하세요! 파이썬!
 
  def callback_func(func):
  # 다른 함수를 매개변수로 입력받음
  # 원하는 시기와 조건에 맞게 특정함수를 실행하게 해주기 때문에
 
    for i in range(5):
        func( )
 

  def print_hello( ):
      print('안녕하세요! 파이썬!') # 5번 반복하게 됨
 

  print_hello( )
 

  callback_func(print_hello)
 
안녕하세요! 파이썬!
안녕하세요! 파이썬!
안녕하세요! 파이썬!
안녕하세요! 파이썬!
안녕하세요! 파이썬!
안녕하세요! 파이썬!

 

 
  def callback_func(func, num):
      for i in range(num):
          func(i)

  def print_hello(num):
      print('안녕하세요! 파이썬!', num)

  def print_hi(num):
      print('하이! 파이썬!', num)
 
  callback_func(print_hello, 3)
 
  # 메모리 주소를 넘김, func에다가 3을 넣음
     -> func 3번 실행 -> num에 0,1,2 넣어줌

  callback_func(print_hi, 5)
 
   # 메모리 주소를 넘김, func에다가 5을 넣음
     -> func 5번 실행 -> num에 0,1,2,3,4 넣어줌
 
안녕하세요! 파이썬! 0
안녕하세요! 파이썬! 1
안녕하세요! 파이썬! 2
하이! 파이썬! 0
하이! 파이썬! 1
하이! 파이썬! 2
하이! 파이썬! 3
하이! 파이썬! 4

 

 

2. 람다 함수(Lambda Function)

람다 함수는 파이썬에서익명의간단한함수를 생성하기 위한 특별한 구문입니다. "익명의 함수"라는 것은 함수에 고유한 이름이 지정되지 않았음을 의미합니다람다 함수는 일반적인 함수(def를 사용하여 정의)와는 달리 줄로 표현되는 짧고 간결한 함수를 생성할  주로 사용됩니다.
* 익명의 함수 = 메모리에 저장되지 않음, 메모리가 절약됨



lambda arguments: expression
반복문을 이용한다던지 일반 함수를 사용한다던지 하면 람다를 크게 사용할 일이 없지만 코드를 더 간결하게 하고 다양하게 하기 위해서 사용한다.

 

  • arguments: 람다 함수에 전달되는 인자들입니다.
  • expression: 반환할 표현식입니다. 이 표현식의 값이 람다 함수가 호출될 때 반환됩니다.

  • 간결성: 람다 함수는 간단한 연산이나 작은 기능을 가진 함수를 간결하게 표현하는 데 유용합니다.
  • 익명성: 람다 함수에는 명시적인 이름이 부여되지 않습니다. 그러나 필요에 따라 변수에 할당할 수 있습니다.
  • 일회성: 일반적으로 특정 작업을 위한 일회성 함수로 사용됩니다.

 

 
 
  def square(x):
    return x ** # 일반함수
 
    ㄴ매개변수를 받아서 그 값을 제곱하여 출력하는 함수
 
  # 일반 함수: 이름이 있음, 메모리에 올라가 있음
  # 람다 함수: 익명임, 메모리에 올라가지 않음 
 
 
 
  lambda x: x ** 2  # 람다 함수
 
   # lambda 변수 : 몸통
   # 람다의 특징은 무조건 리턴형이여서 따로 리턴을 쓰지 않음
   # 함수를 메모리에 저장하지 않았기 때문에 불러서 호출할 수는 없음
 
 
 
 
  square = lambda x: x ** 2 # 람다함수를 객체로 저장하기

  print(square(5)) # 저장해서 출력할 수는 있음, 결과는 같음 (잘 사용하진 않음)
  print(square(4))


  print((lambda x: x ** 2)(4)) # 저장을 안하고 바로 출력
                                           -> (람다함수식) (매개변수) -> 실행가능!
                                             # 한번 실행되고 끝남. 메모리에 올라가지 않음.
 
   # 함수는 원래 코드를 재활용하려는 걸까?
   # 그럼 코드로 써서 하면되지 굳이 람다라는 함수로 만들까?
                       
 
25
16
16
  
  def sort_age(x):
      return x['age']   # 데이터를 age만 뽑아서 x로 출력해줘
 
 
 
                  # x에 하나씩 대입
  people = [{'name': '오렌지', 'age': 30},{'name': '김사과', 'age': 20}, {'name': '반하나', 'age': 25} ] 
 
 
 
                            # x값들을 오름차순으로 정리해서 sorter_people에 넣어줘
  sorted_people = sorted(people, key=sort_age)  
 
 
 
  # sorted() 변수에 저장해야 하는 함수
  # 어떤 기준으로 정리할지 key에 등록 (key=기준이 되는 함수)
 
 
  print(sorted_people)
 
 
[{'name': '김사과', 'age': 20}, {'name': '반하나', 'age': 25}, {'name': '오렌지', 'age': 30}]
 
 
# 위에 일반함수는 sorted를 위해 존재합니다. 다른 곳에서는 쓸모가 없습니다.
  # 메모리에 남겨 놓을 필요가 없고 일회용으로 사용하고 싶은 이런 경우,
     아래의 경우처럼 람다함수를 사용합니다. 
 
 
  people = [{'name': '오렌지', 'age': 30},{'name': '김사과', 'age': 20}, {'name': '반하나', 'age': 25} ]
  sorted_people = sorted(people, key=lambda x: x['age']) # 사용하고 없어질 함수 
  

  print(sorted_people)
 
 
 [{'name': '김사과', 'age': 20}, {'name': '반하나', 'age': 25}, {'name': '오렌지', 'age': 30}]

 

 

3. 람다가 유용하게 사용되는 대표적인 함수

 

 

1. filter 함수

filter()는 파이썬의 내장 함수로, 주어진 함수의 조건을 만족하는 항목만으로 이루어진 이터레이터를 반환합니다. 이 함수는 주로 리스트나 다른 순차적인 데이터 타입에서 특정 조건을 만족하는 항목들만을 필터링할 때 사용됩니다.

 

  • function: 각 항목에 적용되는 함수. 이 함수는 하나의 인자를 받아 참(True) 또는 거짓(False)을 반환합니다.
  • iterable: 필터링 될 이터러블 객체 (예: 리스트, 튜플, 문자열 등)
 
 
  li = [2, 5, 7, 10, 15, 17, 20, 22, 25, 28]
 
  def even(n):
      if n % 2 == 0:
          return True
      else:
          return False  # 짝수 True, 홀수 False

  result = list(filter(even, li))  # even( )함수에 li를 넣어주기
  print(result)                        # 짝수만 걸러짐
 
 
  # filter() : 함수에 만족하는 것만 뽑아서 list 만들어줌
 
 
[2, 10, 20, 22, 28]

 

  
 
  numbers = [1, 2, 3, 4, 5, 6]    
  even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
                                              # 람다가 맞는 것만 리턴시킴
  print(even_numbers)  


[2, 4, 6]

 

 

 

2. map 함수

map()는 파이썬의 내장 함수로, 주어진 함수를 이터러블의 모든 항목에 적용하여 결과를 반환하는 이터레이터를 생성합니다. 이 함수는 주로 리스트나 다른 순차적인 데이터 타입의 항목 각각에 함수를 적용할 때 사용됩니다.

 

필터는 데이터가 5개가 있다면 여기에 조건을 주고  조건이 만족하는 거냐 만족하지 않는거냐를 확인해서 조건이 만족하는 것만 뽑아주는 것

맴함수는 5개의 자료가 있다면 이 5개의 자료에 수식을 적용해서 이 수식을 적용한 자료가 리턴됩니다.

 

function: 각 항목에 적용될 함수.

iterable: function에 의해 처리될 이터러블 객체(예: 리스트, 튜플, 문자열 등). map() 함수는 여러 개의 이터러블을 동시에 처리할 수 있습니다.

  
  numbers = [1, 2, 3, 4, 5]     # 5개의 데이터가 numbers에 저장
 
  squared_numbers = list(map(lambda x: x**2, numbers))
                                   # 람다에다가 특정값을 받으면 제곱하라고 함
 
 
  print(squared_numbers)                                                             


[1, 4, 9, 16, 25]
 
  list1 = [1, 2, 3]            # 두 묶음의 자료가 있음
  list2 = [4, 5, 6]
 
  summed = list(map(lambda x, y: x + y, list1, list2))   
                    # 두묶음의 자료에 값들을 각각 더해서 리턴해줘
 
  print(summed) 


[5, 7, 9]

 

 
  words = ["apple", "banana", "cherry"]
  uppercase_words = list(map(str.upper, words))
  print(uppercase_words)  
 
['APPLE', 'BANANA', 'CHERRY']

 

 
  words = ["apple", "banana", "cherry"]
 
 
                                 upper라는 메소드를 보내서 받아줘
  uppercase_words = list(map(str.upper, words)) 
  print(uppercase_words) 
 
 
 # map (함수 _______, 매개변수), list1, list2)
  # map이 람다는 자료를 호출하여 필터링하기 때문에 결국 콜백함수이다.
 
['APPLE', 'BANANA', 'CHERRY']

 

map() 함수는 결과를 이터레이터 형태로 반환하기 때문에 그 결과를 직접 출력하거나, 인덱싱하거나, 슬라이싱하기 위해서는 list()나 비슷한 함수를 사용하여 이터레이터를 실제 리스트나 다른 데이터 구조로 변환해야 합니다.

map()은 filter()와 달리 항목의 개수를 변경하지 않습니다. 이터러블의 각 항목은 함수를 거쳐 변환되지만, 그 결과의 개수는 원래 이터러블의 개수와 동일합니다.

복잡한 데이터 처리나 변환 작업에 대해서는 파이썬의 컴프리헨션(comprehension) 구문을 사용하는 것이 map() 함수를 사용하는 것보다 더 명료하고 가독성이 좋을 수 있습니다.

 

'Python > 개념' 카테고리의 다른 글

Day 7-1. 파이썬 상속  (0) 2024.03.18
Day 6-3. 객체지향과 클래스  (0) 2024.03.18
Day 6-1. 변수의 범위  (0) 2024.03.15
Day 5-2. 사용자 정의 함수  (0) 2024.03.15
Day 5-1. 컬렉션과 반복문  (0) 2024.03.15