First-Class Functions

rang-dev·2020년 6월 2일
1

Programming Terms: First-Class Functions를 유투브에서 보고 정리합니다.

  1. First-Class Functions
  2. Closures
  3. Decorators

First-Class Functions

First-Class Functions: A Programming language is said to have first-class functions if it treats functions as first-class citizens

First-Class Citizen (Programming): A first-class citizen (sometimes called first-class objects) in a programming language is an entity which supports all the operations generally available to other entities. These operations typically include being passed as an argument, returned from a function, and assigned to a variable.

프로그래밍 언어에서 함수들을 first-class citizens로 취급하면 first-class functions이 있다고 말하는데, 이 first-class citizen는 argument로 전달이 가능하고 function에서 return될 수 있으며 변수에 할당 가능한 객체들을 의미한다.

즉, 함수가 argument로 전달이 되거나, function에서 함수를 return하거나 변수에 함수를 할당할 수 있다는 것이다.

그럼 first-class functions을 선언하는 방법이 따로 있는걸까?
-> What is first class function in Python

파이썬의 모든 functions은 first-class functions라고 한다. 그러니까 모든 함수는 argument로 전달 가능하고 함수에서 return될 수 있으며 변수에 할당될 수 있다.

함수를 변수로 할당하기

def square(x):
	return x*x

f = square(5)

print(square)
> <function square at 0x7fc8d5dd2e18>

print(f)
> 25

함수 호출시 square()square은 다르다. ()은 함수를 실행하라는 의미이다. ()없이 함수이름만 적으면 함수 그 자체를 의미하며, 여기서 first-class function의 개념이 적용되는데 f = square로 함수를 f에 할당할 수 있다.

함수를 argument로 전달하기

def square(x):
	return x*x

def my_map(func, arg_list):
	result = []
	for i in arg_list:
		result.append(func(i))
	return result

squares = my_map(square, [1,2,3,4,5])

print(squares)
> [1, 4, 9, 16, 25]

my_map함수는 func파라메터로 함수들을 전달받을 수 있다. 전달된 함수들은 for문 안에서 적용이 된 후 result에 값으로 추가된다. my_map에서 함수 인자는 ()을 포함하지 않아야한다는 것을 명심하자.

일반적으로 우리가 string이나 숫자를 arguments로 전달했을 때와 마찬가지로 어느 함수든지 argument로 전달이 가능하다.

만약 square함수 말고 cube라는 함수를 다음과 같이 새로 선언했다고 하자.

def cube(x):
	return x*x*x

cube함수 또한 func로 전달될 수 있다. 단, my_map함수보다 먼저 선언되어야 한다.

cubes = my_map(cube, [1,2,3,4,5])

print(cubes)
> [1, 8, 27, 64, 125]

함수를 다른 함수에서 return하기

def logger(msg):

	def log_message():
    	print('Log:', msg)
    
    return log_message
    
log_hi = logger('Hi!')
log_hi()
> Log: Hi!

logger함수는 log_message함수를 return한다. 하지만 여기서 잘 살펴보면 log_message()가 아닌 log_message를 return하고 있으므로 함수 그자체를 의미하는 것이지 함수를 실행하라는 것이 아니다.

log_hi = logger('Hi!')를 하면 log_hi는 log_message를 가르키게 되고 log_hi가 log_message 함수 그 자체가 된다. log_hi()를 해주어야 비로소 log_message함수가 실행되는 것이다. 이때 처음에 logger함수에서 받아왔던 msg를 log_message 함수 내에서 사용할 수 있는데 이것을 closure라고 한다.

왜 함수에서 함수를 return하는게 유용할까? 다음의 예시를 살펴보자.

def html_tag(tag):

	def wrap_text(msg):
    	print('<{0}>{1}</0>'.format(tag, msg))
        
    return wrap_text
        
 print_h1 = html_tag('h1')
 print_h1('Test Headline!')
 print_h1('Another Headline!')
 > <h1>Test Headline!</h1>
   <h1>Another Headline!</h1>
  
 print_p = html_tag('p')
 print_p('Test Paragraph!')
 > <p>Test Paragraph!</p>

아까 살펴봤던 것과 비슷하게 print_h1 = html_tag('h1')을 하면 tag에는 h1이 저장되고 print_h1은 wrap_test 그 자체가 된다.(return할때 함수 뒤에 ()가 붙지 않았으므로)

html_tag에서 넣어준 text는 바꾸지 않으면서 print_h1에 Test Headline를 argument로 넣을수도 있고 Another Headline이라는 argument를 넣을수도 있게된다.


다음글: Closures

profile
지금 있는 곳에서, 내가 가진 것으로, 할 수 있는 일을 하기 🐢

0개의 댓글