function은 특정 작업을 수행하기 위해 사용되는, 잘 짜인 재사용 가능한 코드 블록이에요.
Functions는 애플리케이션을 더 잘 모듈화해 주고 코드를 높은 수준으로 재사용할 수 있게 해줘요.
Python은 다른 프로그래밍 언어들처럼 바로 쓸 수 있는 내장 함수(print, map 등)를 제공해요.
직접 함수를 정의할 수도 있는데, 이런 함수를 user-defined functions라고 해요.
함수는 콘솔에 메시지를 출력하는 것처럼 간단한 일부터 꽤 복잡한 일까지 할 수 있어요.
함수 안의 코드를 실행하려면 함수를 호출해야 하는데, 함수 이름 뒤에 괄호 [()]를 붙이면 돼요.
arguments라고 하는 데이터는 괄호 안에 넣어 함수에 전달할 수 있어요.
함수 정의에는 parameters가 하나도 없을 수도 있고 여러 개일 수도 있어요.
매개변수는 함수가 어떤 인자를 받아들일지 정의해요.
매개변수는 어떤 _타입_의 인자가 전달될지를 정해요.
인자는 함수가 호출될 때 실제로 전달되는 _값_이에요.
함수는 매개변수에 전달되는 인자에 따라 서로 다른 작업을 할 수 있어요.
함수는 return 키워드를 사용해 값을 반환할 수도 있어요.
함수가 반환하는 값을 return value라고 해요.
반환값은 함수를 호출한 쪽으로 돌아가요.
Python에서는 def 키워드로 함수를 만들어요.
def 뒤에는 함수 이름과 괄호 [()]가 와요.
괄호 안에는 매개변수를 쉼표로 구분해서 적어요.
닫는 괄호 뒤에 오는 콜론(:)은 함수 시그니처와 함수 본문을 구분해요.
함수 본문은 함수가 호출될 때 실행되는 코드 블록이에요.
함수 본문은 들여쓰기해요.
들여쓰기는 중요해요. Python은 들여쓰기를 보고 코드 블록이 어디서 끝나는지 알기 때문이에요.
return 키워드를 사용하면 함수에서 값을 반환할 수 있고, 이 값은 함수를 호출한 쪽에서 사용할 수 있어요.
def function_name(parameter1, parameter2, ...):
# function body
return parameter1 + parameter2
매개변수나 반환값이 없는 함수를 정의할 수도 있어요.
def function_name():
# function body
pass
함수에는 본문이 반드시 있어야 해요. 본문이 아무 일도 하지 않더라도 말이에요. 그렇지 않으면 프로그램을 실행할 때 들여쓰기 오류가 발생해요:
>>> def my_bodyless_func():
...
File ~/temp.py:1
^
IndentationError: expected an indented block
함수를 호출할 때는 함수 이름 뒤에 괄호 [()]를 붙여요.
함수에 전달하는 인자는 괄호 안에 쉼표로 구분해서 넣어요.
다음 함수를 살펴봐요:
def greet():
print("Hello")
위 함수는 다음과 같은 문법으로 호출할 수 있어요:
>>> greet()
Hello
인자는 함수가 호출될 때 함수에 전달되는 값이에요. 인자는 다른 함수나 클래스를 포함해 어떤 데이터 타입이든 될 수 있어요.
두 수를 더하는 add 함수를 정의해 봐요:
def add(first, second):
print(first + second)
매개변수 first와 second는 add 함수가 어떤 인자를 받을지 정의해요.
(parameter와 argument라는 단어는 종종 부정확하게 혼용되기도 해요.)
함수가 호출되면 인자가 함수로 전달돼요.
두 매개변수 모두에 인자를 전달해야 해요. 그렇지 않으면 TypeError가 발생해요.
>>> add(2, 3)
5
# Function can be called multiple times, with different parameters
>>> add(4, 3)
7
>>> add(5, 6)
11
# Passing an incorrect number of parameters will raise a `TypeError`
>>> add(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() missing 1 required positional argument: 'second'
>>> add(2, 3, 4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: add() takes 2 positional arguments but 3 were given
반환값은 함수를 호출한 쪽으로 돌아가는 값이에요.
return value는 다른 함수나 클래스를 포함해 어떤 데이터 타입이든 될 수 있어요.
함수를 호출한 쪽은 이 값을 사용해 추가 작업을 할 수 있어요.
함수가 return value를 명시적으로 정의하지 않으면 Python 인터프리터가 None 값을 반환해요.
add 함수를 정의해 봐요:
def add(first, second):
return first + second
반환값을 변수에 저장한 다음 출력할 수 있어요:
>>> result = add(2, 3)
>>> print(result)
5
# Type of result is `int`
>>> type(result)
<class 'int'>
# We can also perform operations on the return value
>>> result * 2
10
# A function without an explicit return value will return `None`
>>> def log(message):
print(message)
# Hello is printed because of print(message), but return value is `None`
>>> return_value = log("Hello")
Hello
>>> return_value
None
return을 사용하면 함수가 즉시 종료되고 값이 호출한 쪽으로 반환돼요.
>>> def show(first, second):
print(first)
return first
print(second)
# second never gets printed, because the function exits after the return statement
>>> show(1, 2)
1
복잡한 프로그램은 더 작은 부분으로 나눌 수 있어요. 서로 다른 함수로 각각의 구체적인 작업을 수행할 수 있어요.
프로그램이 다음과 같은 작업을 해야 한다고 가정해 봐요:
프로그램을 더 작은 부분으로 나눌 수 있어요.
def circle_area(radius):
return 3.14 * radius * radius
def rectangle_area(length, breadth):
return length * breadth
def triangle_area(base, height):
return 0.5 * base * height
이제 원하는 순서대로 함수를 호출할 수 있어요.
>>> circle_area(2)
12.56
>>> triangle_area(2, 3)
3.0
>>> rectangle_area(2, 3)
6
>>> rectangle_area(1, 2) + circle_area(2) + triangle_area(1, 2)
15.56
변수(또는 이름)가 함수 안에서 정의되면, 함수 스코프(또는 지역 네임스페이스) 안에서만 접근할 수 있어요. 함수 스코프 밖에 같은 이름의 변수가 있더라도 마찬가지예요.
함수 밖, _모듈 수준_에서 정의된 변수는 _전역 네임스페이스_에 있는 것으로 봐요. 함수 밖이지만 둘러싸는 함수나 클래스 안에서 정의된 변수는 _비지역 네임스페이스_에 있어요.
Python은 프로그램이 실행될 때 변수 이름을 찾기 위해 LEGB 규칙(Local, Enclosing, Global, Built-in)을 사용해요:
그래도 이름을 찾지 못하면 Python은 NameError exception을 발생시켜요.
# Global namespace.
general_favorite = "apples"
def alices_favorite():
# Local namespace.
favorite = "cherries"
# This works because Python will eventually find general_favorite in the global namespace.
# Python will find 'print' in the built-in namespace.
print(f'Alice has always liked {favorite}, but most people like {general_favorite}.')
def our_favorite_fruits():
# Enclosing or nonlocal namespace.
yours = "peaches"
def my_favorite():
# Local namespace.
mine = "pears"
# This works because Python will eventually find 'yours' in the enclosing/nonlocal namespace.
print(f'My favorite is {mine}, but you like {yours} instead.')
# This works because Python will eventually find 'general_favorite' in the global namespace.
print(f'Everyone seems to like {general_favorite}')
# This function is in the local namespace of the 'our_favorite_fruits' function.
my_favorite()
# This will raise NameError: name 'favorite' is not defined, because the variable favorite is local to alices_favorite.
print(favorite)
변수 이름을 지역 함수 스코프 밖에서 접근할 수 있게 하려면(또는 함수 스코프 밖에 정의된 변수를 수정하려면), global이나 nonlocal 키워드를 사용해야 해요.
global 키워드를 사용하면 Python은 _전역 네임스페이스_에서 이름을 찾기 시작해요.
그러면 변수에 값을 대입할 때 지역 버전을 새로 만드는 대신 전역 변수를 수정해요.
global로 변수를 선언하면 그 변수는 전역 네임스페이스에 _추가_돼요.
따라서 global은 신중하게 사용해야 해요. 전역 변수를 추가하거나 수정하면 그 값을 사용하는 다른 모든 코드에 영향을 줄 수 있기 때문이에요.
nonlocal 키워드는 Python에게 _비지역 또는 둘러싸는 네임스페이스_에서 변수를 찾거나 만들라고 알려줘요.
함수가 다른 함수나 클래스 안에 중첩되어 있고, 바깥 함수의 변수와 스코프에 접근해야 할 때 사용해요.
Python에서는 함수를 변수에 대입하거나 다른 함수의 인자로 전달할 수 있어요.
반환값으로 사용할 수도 있어요.
함수는 시퀀스(list, tuple 등)에 넣거나 dict의 값으로 넣을 수도 있어요.
함수는 다른 객체를 쓸 수 있는 곳이면 어디든 사용할 수 있어요.
함수는 일급 객체이기 때문이에요.
그래서 함수는 특별한 속성을 가지고 있고, 직접 사용자 정의 속성을 가져오고 설정하는 것까지 정의할 수 있어요.
# print is a function
# A function can be assigned to a variable.
>>> function_as_variable = print
>>> function_as_variable("Hello")
Hello
>>> type(fake_print)
<class 'builtin_function_or_method'>
# Functions can be passed as an argument to another function.
>>> def check_print(func):
func("Hello")
>>> check_print(print)
Hello
# Function can be used as an item in a sequence.
>>> my_list = [print, "Hello"]
>>> my_list[0]("Hello")
Hello
# Functions can be used as a value in a dictionary.
>>> my_dict = {"key": print}
>>> my_dict["key"]("Hello")
Hello
# Functions can be returned from a function.
>>> def return_func():
return print
>>> return_func()("Hello")
Hello
함수는 다른 함수 안에 중첩할 수도 있어요.
def outer():
num = 10
# This is a nested, or "inner" function.
def inner():
print(num)
# Outer function calling inner function
inner()
내부 함수는 바깥 함수에서 정의한 num 변수에 접근할 수 있어요.
>>> outer()
10
Python의 함수에는 특별한 속성이 있어요. 그중 몇 가지는 다음과 같아요:
__name__: 함수의 이름__doc__: 함수의 문서 문자열__module__: 함수가 정의된 모듈__globals__: 함수의 전역 변수 딕셔너리__code__: 함수의 명령을 담고 있는 코드 객체>>> def add(first, second):
return first + second
# Function name
>>> print.__name__
'print'
>>> len.__name__
'len'
>>> add.__name__
'add'
# Function documentation
>>> abs.__doc__
'Return the absolute value of the argument.'
# Module
>>> len.__module__
'builtins'
>>> add.__module__
'__main__'
함수 속성의 전체 목록은 Python 데이터 모델에서 볼 수 있어요.