Python:Function

aiden·2023년 6월 5일
0

Python

목록 보기
5/14

함수는 하나의 기능을 하는 명령어들을 묶어 이름을 붙인 것이다. 함수는 필요한 데이터를 입력받을 수 있으며, 결과를 caller에게 반환한다.
함수를 실행하려면 함수를 호출하면 된다. 동일한 동작을 하기 위해 같은 코드를 여러 번 작성할 필요 없이 같은 함수를 여러 번 호출하면 코드가 간결해진다.

Definition of Function

다음과 같이 함수를 정의할 수 있다.

함수는 헤더와 몸체로 나뉘는데, 헤더는 키워드 def로 시작하고 함수의 이름과 매개변수를 가진다. 몸체에는 명령어들이 나열되어있다. 결과를 반환할 때에는 return 키워드를 이용하며, return 문장이 실행되면 함수는 종료한다.

Argument, Parameter

인수(argument)는 함수 호출 시 함수에 전달되는 값, 매개변수(parameter)는 이 값을 전달받는 변수이다.
함수가 호출되면 인수가 함수의 매개변수에 전달된다.
함수를 호출할 때 모든 매개변수에 값을 전달해야 한다. 즉, 매개변수와 전달되는 인자의 개수는 동일해야 한다.

함수는 여러 개의 매개변수를 가질 수 있으며 인자로 변수를 전달할 수 있다.

Return Value

함수를 실행한 결과를 반환할 수 있다. 반환값은 return 뒤에 오는 수식, 변수, 리터럴 등이 될 수 있다. 아무런 값도 반환하지 않는 경우, 파이썬에서 함수는 None을 반환한다.
return 뒤에 아무것도 적지 않고 return하게 되면, 값이 반환되지 않고 함수를 종료할 수 있다. 이러한 함수를 void 함수라 한다.

❗함수 호출문이 함수의 정의보다 먼저 나오면 안된다. 함수를 호출하려면 함수가 정의돼있어야 한다. 다만 함수 안에서 호출된 함수는 순서와 상관 없이 허용된다. 함수 안에 있기 때문에 바로 실행되지 않기 때문이다.

다음의 경우 문제가 발생하지만,

아래와 같이 작성하는 것은 문제가 발생하지 않는다.

따라서 파이썬 코드 작성 시 모든 문장을 함수 안에 넣는 것도 좋다. main() 함수를 작성해 주된 기능을 하도록 하고 코드의 마지막에 main()을 호출하면 된다.

Default Argument

파이썬에서는 함수의 매개변수로 기본값을 지정할 수 있다. 이를 디폴트 인수라고 한다. 함수를 호출할 때 모든 매개변수에 인자들을 전달해주어야 하는데, 미리 디폴트 인수를 지정해 인자를 적게 넣는 경우에도 오류가 나지 않고 실행되도록 할 수 있다. 다음 예시와 같이 작성한다.

def person(name, age, job = "없음"):
    print("이름 : %s 나이 : %d 직업 : %s" %(name, age, job))
    
person("Kim", 35, "engineer")
person("Lee", 25)
person("Jung", 27)

이름 : Kim 나이 : 35 직업 : engineer
이름 : Lee 나이 : 25 직업 : 없음
이름 : Jung 나이 : 27 직업 : 없음

Keyword Argument

일반적으로 함수를 호출할 때 인자를 전달하는 경우 매개변수에 순서대로 전달된다(positional argument 위치 인수). 하지만 키워드 인수를 이용하면 인수들 앞의 키워드를 통해 순서 상관없이 지정하여 전달할 수 있다. 파이썬에서는 다음과 같은 방식이 허용된다.

❗이 때 주의할 점은, 위치 인수와 키워드 인수가 섞일 수 있지만 위치 인수가 키워드 인수보다 앞에 있어야 하며 키워드 인수 뒤에 위치 인수가 나올 수 없다.

calc(10, y = 20, z = 30) //가능
calc(x = 10, 20, 30) //불가

call-by-value & call-by-reference

함수를 호출할 때, 변수를 전달하는 경우 변수의 값이 함수에 전달된다. 이를 값에 의한 호출 또는 값에 의한 전달(pass-by-value)이라 한다. 다음 예시를 보자.

def modify(n):
    n += 1

k = 10
print(k)
modify(k)
print(k)

10
10

변수 k를 함수 ex에 전달했으나 k 값은 함수 호출 이후에도 변경되지 않았다.

문자열의 경우에도 동일하다. 다음 예시를 보자.

def modify(s):
    s += " add this"

str = "This is original"
print(str)
modify(str)
print(str)

This is original
This is original

변수 str을 함수 ex에 인자로 전달했으나 함수 호출 뒤에도 str의 값은 변하지 않았다.

이는 숫자나 문자열이 변경 불가능한 객체(immutable object)이기 때문이다. 숫자나 문자열을 변경하는 경우 새로운 객체가 생성된다. id() 함수를 통해 이를 확인할 수 있다.

str = "This is original"
print(id(str), str)
str += " add this"
print(id(str), str)

2123121897952 This is original
2123121893712 This is original add this

변경 전과 후에 변수 str이 가리키는 주소가 변경되었음을 알 수 있다.

리스트와 같은 변경 가능한 객체(mutable object)의 경우 함수에 참조값이 전달되고 값이 변경되면 변경 가능한 객체이기 때문에 새로운 객체를 생성하는 것이 아니라 기존의 객체가 변경된다.

def modify(l):
    l += [6, 7]
    
list = [1, 2, 3, 4, 5]
print(list)
modify(list)
print(list)

[1, 2, 3, 4, 5].
[1, 2, 3, 4, 5, 6, 7]

❗주의
이 때, 다음과 같이 작성하면 변경되지 않는다.

def modify(l):
    l = l + [6, 7]
    l = l + [8, 9]
    
list = [1, 2, 3, 4, 5]
print(list)
modify(list)
print(list)

[1, 2, 3, 4, 5].
[1, 2, 3, 4, 5]

다음과 같이 작성해야 리스트가 변경된다.

def modify(l):
    l += [6, 7]
    l += [8, 9]
    
list = [1, 2, 3, 4, 5]
print(list)
modify(list)
print(list)

[1, 2, 3, 4, 5].
[1, 2, 3, 4, 5, 6, 7, 8, 9]

이유는 잘 모르겠다.

Local Variable & Global Variable

파이썬에도 지역변수와 전역변수가 존재한다. 파이썬의 scope rule에 대해서는 후에 공부할 것이다. 지역 변수는 함수 안에서 선언된 변수이고 전역 변수는 한수 외부에서 선언된 변수이다.

지역변수

지역변수는 함수 내부에서만 사용할 수 있으며 함수 호출이 끝나면 사라진다. 함수 외부에서는 지역변수를 사용할 수 없다.

전역변수

함수 외부에 정의된 변수를 전역 변수라 한다. 상수가 아닌 경우 전역변수를 사용하기보다는 함수로 감싸는 것이 좋다.

다음 예시를 통해 지역변수와 전역변수에 대해 이해할 수 있다.

함수 내 정의된 지역변수가 없으면 전역변수가 사용된다.

함수 내에서는 지역변수가 우선으로 사용된다. 전역변수는 무시된다.

함수 내에서 전역변수를 사용하고 싶은 경우, global 키워드로 명시해주면 된다.

이러한 global 선언 없이 위의 코드를 작성했을 경우 함수 내에서 전역변수와 지역변수를 모두 사용하려는 것이 되므로 오류가 발생한다. global 선언을 통해 전역변수 s를 사용할 것임을 명시한다면 이후의 s는 전역변수 s를 의미하는 것이다.
결국 함수 내에서 하나의 변수는 지역변수 또는 전역변수 중 하나만 될 수 있고 같이 사용될 수 없다.

👉🏻함수 호출 시 전달하는 인자를 받는 매개변수 또한 함수의 지역변수이다.

여러개의 반환값

파이썬에서는 한 함수가 여러개의 return값을 가질 수 있다.

def example():
    return 1, 2, 3

a, b, c = example()
print(a, b, c)

result = example()
print(result)

1 2 3
(1, 2, 3)

파이썬의 함수에서 여러개의 값을 반환할 때 튜플을 이용해서 반환한다는 것을 알 수 있다.

Lambda

람다 함수는 이름이 없고 몸체만 있는 무명 함수이다. 람다 함수는 여러 개의 인수를 가질 수 있으나 리턴값은 하나만 가질 수 있다. 또, 람다 함수 내에서 print() 함수를 호출할 수 없고 연산만 가능하며 전역변수를 참조할 수 없다.
구조는 다음과 같다.

람다함수를 이용하면 함수를 보다 간단하게 만들 수 있다.

sum = lambda x, y: x+y;
/*일반적인 함수의 경우
def sum(x, y)
	return x + y*/

다음은 람다함수의 활용 예시이다.

list = [lambda x : x * 10, lambda x : x * 20, lambda x : x * 30]
for f in list:
    print(f(1))
//람다함수로 리스트 구성 가능

10
20
30

min = lambda x, y : x if x < y else y
print(min(1, 101))
//변수에 람다함수를 대입해 함수의 이름처럼 사용 가능

1

Recursive Function

정말정말정말 중요한 재귀함수. 내가 파이썬을 다시 공부해야겠다고 생각하게 된 이유 중 하나였다. 자료구조와 알고리즘을 공부할 때 그렇게 많이 사용하게 될 줄은 몰랐다.

재귀함수란 함수 내에서 자기 자신을 호출하는 함수이다. 다음 구조를 가진 함수는 재귀함수이다.

함수 내에서 자신을 호출한 후, 실행중인 함수가 끝날때까지 함수 호출 이후의 명령문은 수행되지 않는다. 함수 내에 종료 조건이 포함되어 있어야한다. 그렇지 않으면 함수를 빠져나올 수 없다.

대표적인 예시로는 재귀함수를 이용해 구현한 팩토리얼 함수가 있다.

Module

파이썬에서, 함수를 모아서 저장해놓은 파일을 모듈이라 한다. 모듈 안의 함수들은 import 키워드를 통해 다른 모듈로 불러올 수 있다. 모듈 중 main 모듈은 다른 모듈들의 최상위 모듈이다. 파일의 이름은 모듈 이름에 .py 확장자를 붙이면 되고, 모듈 안에서 __name__ 문자열을 통해 다른 모듈의 이름에 접근 가능하다.

fibo.py라는 이름의 파일이 다음과 같다고 하자.

#파일명 fibo.py
#피보나치 수열 모듈
def fib(n):
    a, b = 0, 1
    i = 0
    while i < n:
        print(b, end=' ')
        a, b = b, a+b
        i += 1
    print()

main.py 파일에서 fibo 파일을 import하는 경우 fibo.py 파일이 실행 중인 main.py와 같은 디렉토리에 존재해야 한다.

#파일명 main.py
#main 모듈
import fibo
fibo.fib(10)
print(fibo.__name__)

1 1 2 3 5 8 13 21 34 55
fibo

모듈에서 함수를 불러오는 방법도 있다.

from fibo import * //모듈에서 모든 함수 포함
from fibo import fib //fib 함수만 포함

fib(10)

파이썬 모듈을 다음과 같이 명령어 프롬프트에서 실행하는 경우,

"__name__"이 "__main__"으로 변경되고 모듈 안의 코드가 실행된다. fibo 모듈의 끝부분에 다음과 같은 코드를 추가하면 명령어 프롬프트를 통해 실행할 때 fib() 함수가 호출된다.

모듈화를 통해 큰 문제를 작게 분할하고 이를 다시 조립하는 것은 구조적이고 짜임새있는 프로그램을 작성하는 데 도움이 된다. 따라서 코드의 모든 부분을 함수에 작성하고, main 함수를 마지막에 실행하는 것이 바람직하다. 다음과 같은 코드를 마지막에 포함하여 이 모듈이 단독으로 실행될 때(이 모듈이 다른 모듈에 임포드되는 것이 아니라 직접 실행됐을 때) main()을 호출하도록 하는 것이 좋다.


자주 사용되는 아래 코드에 대해 알아두는 것이 좋겠다.

if __name__ == "__main__":
	main()
profile
파인애플 좋아하세요?

0개의 댓글