Python

04.Function(1)

seunghyeoniya 2023. 8. 5. 21:19

-------------------------

04.Function

-------------------------

** Function

1. 개요

=> 별도의 메모리 공간을 할당받아서 독립적으로 수행되는 코드의 집합

=> 목적은 코드의 모듈화(분할)와 동일한 코드의 중복을 제거

 

2. 종류

=> Built-In Function(Maker Function) : 파이썬이 제공하는 함수

=> User Define Function : 개발자가 필요에 의해서 만든 함수

=> 3rd party Function : 다른 개발자가 만들어서 제공하는 함수 - 되도록이면 파이썬 중앙 저장소에서 제공하는 것만 이용

 

3. 파이썬에서는 함수도 데이터입니다.

-> 파이썬에서는 함수를 변수명처럼 사용하여도 에러가 생기지 않는다. 왜냐하면 f의 이름을 가진 함수의 데이터를 참조해주기 때문이다.

 

4. Built-In Function

=> 코드에서 확인 : dir(__builtins__))

=> 문서에서도 확인 가능 : https://docs.python.org/3/library/functions.html

=> 버전마다 다름

 

5. 사용자 정의 함수

1) 함수 선언(정의)

def 함수이름(매개변수 나열):

함수 내용

return 데이터

=> 함수 이름은 사용자 정의 명칭을 사용

=> 매개변수는 없을 수도 있습니다.

=> return 생략 가능

 

2) 함수 호출(call, 실행)

함수이름(매개변수에 대입할 데이터 나열)

# Hello Python을 3번 출력

def display():

for i in range(3):

print("Hello Python")

display()

 

# Hello Java 출력

print("Hello Java")

 

# Hello Python을 3번 출력

display() # 같은 작업을 여러 번 반복하려고 할 때 함수를 사용한다.

print(display) # 함수 이름만 사용하면, 저장한 곳을 참조한다. id를 출력한다.

 

3) 함수를 호출한 곳으로 돌아가기 : return

=> 함수 내에서 return을 만나면 함수를 호출한 곳으로 돌아갑니다.

=> 돌아갈 때 데이터를 1개 가지고 갈 수 있습니다.

return 데이터 를 이용하면 데이터를 가지고 돌아갑니다.

함수를 호출한 곳에 return 되는 데이터가 남겨지는 것과 같습니다.

=> 파이썬은 ,를 이용해서 데이터를 나열하면 tuple로 간주

ex. 10, 20 => (10, 20)

-> tuple은 행(row)와 같다.

=> 이전의 파이썬 문법에서는 함수의 헤더에 리턴되는 자료형을 적지 않았지만,

최근에는 가독성 문제 때문에 헤더 부분에 리턴되는 데이터의 타입을 기재하는 경우가 많습니다.

return되는 데이터가 없을 때는 데이터의 타입에 None이라고 기재합니다.

def display() -> 리턴되는데이터타입:

for i in range(3):

print("Hello Python")

ex.

def display() -> None :

for i in range(3):

print("Hello Python")

 

=> return되는 데이터가 있으면 그 결과를 가지고 다른 작업을 수행할 수 있습니다.

return이 없으면 일반적으로 매개변수로 대입된 데이터를 수정합니다.

 

def intAddwithInt(a, b):

return a + b

 

# 함수가 종료되고 다시 함수를 호출하기 때문에 어느 한 순간에 하나의 스택만 존재한다.

result = intAddwithInt(100, 300)

x = intAddwithInt(result, 600)

print(x)

 

# 함수의 수행이 종료되기 전에 다른 함수를 호출하기 때문에 두 개의 스택이 동시에 존재하는 경우가 발생한다.

print(intAddwithInt(intAddwithInt(100,300),600))

 

# 파이썬은 여러 개의 데이터를 나열해서 리턴하는 것이 가능

# 여러 개의 데이터를 나열해서 리턴하면 하나의 튜플로 만들어서 리턴

def intOpWithInt(a, b):

# 튜플로 만들어서 리턴, 깨알) 데이터 분석을 할 것이면 이 방법을 권장

return a + b, a - b

# 튜플 전체를 하나의 변수로 받기

t = intOpWithInt(100,200)

print(t)

# 튜플을 분해해서 받기

add, sub = intOpWithInt(100,200)

print(add, sub)

 

4) argument(매개변수, 인수, 인자, parameter)

=> 함수를 호출할 때 함수에게 넘겨주는 데이터

=> 없을 수도 있고 여러 개 일수도 있습니다.

=> 함수를 호출할 때 매개변수가 있는 함수의 경우 매개변수를 전달하지 않으면 에러가 발생

=> 최근에는 매개변수의 자료형을 명시하는 것을 권장합니다.

매개변수 이름 다음에 콜론(:)을 적고 자료형 기재 가능

 

def add(a : int, b : int) -> int:

# 튜플로 만들어서 리턴

return a + b

print(add(100, 300))

 

int add(int a, int b) <-> UML 표기법 : ex. add(c : int,d : int) -> int

결과 호출 호출 결과

 

=> call by value & call by reference - 매개변수 전달방법

scala data는 값이 전달되는 형태이고 vector data(collection, container)는 참조가 전달되는 형태로 동작한다.

함수를 호출할 때 scala data를 넘겨주면 함수 내부에서 데이터를 변경해도 외부의 데이터는 변경되지 않습니다.

vector data를 넘겨주면 함수 내부에서 함수 외부의 데이터를 수정할 수 있습니다.

 

def callByValue(a : int) -> None:

a = 20

print(a)

 

x = 30

callByValue(x) # 20이 출력된다.

print(x) # 30이 출력된다.

-> ex. 책을 복사해서 주는 것.

 

def callByReference(li : list) -> None:

li[0] = 20

print(li)

l = [100,200,300]

callByReference(l) # vector data를 줘서(참조를 주었기 때문에) 20, 200, 300이 된다.

print(l) # vector data를 줘서(참조를 주었기 때문에) 20, 200, 300이 된다.

-> ex. 책을 빌려주는 것

 

=> pure function(순수 함수)

함수 내부에서 함수 외부의 데이터를 변경하지 않고 매개변수가 동일하면 항상 동일한 결과를 리턴하는 함수

 

=> 매개변수의 기본값을 설정하는 것이 가능

매개변수이름 = 값 의 형태로 작성하면 매개변수의 값을 생략하면 기본값이 설정됩니다.

기본값이 설정된 매개변수를 호출할 때 생략할 수 있습니다.

 

=> 함수를 호출할 때 매개변수 이름과 값을 같이 전달할 수 있습니다.

# 파이썬은 함수를 호출할 때 매개변수 이름과 함께 데이터를 전달할 수 있습니다.

print("반승현", "임한별", "밀리엄", sep="\t")

 

=> 매개변수의 unpacking

매개변수가 여러 개일 때 list나 tuple 또는 set으로 한꺼번에 전달이 가능합니다.

list나 tuple 그리고 set을 분할해서 매개변수에 대입합니다.

매개변수로 대입할 때 앞에 별(*)을 붙여서 전달합니다.

dict를 전달하면 key가 순서대로 대입됩니다.

dict의 value를 전달하고자 하는 경우는 별별(**)을 붙여서 전달하면 됩니다.

 

-> 낱개로 주는 것과 묶어서 주는 것 중에 더 편한 방법으로 사용자가 결정해서 이용하면 된다.

 

def collection(a, b):

print(a, end=" ")

print(b)

collection(10, 20)

> 10 20

 

# List를 분할해서 a에 100 b에 200이 대입

collection(*[100, 200])

> 100 200

 

# dict는 *이 1개이면 key 값이 매개변수에 전달됩니다.

collection(*{"key1": 100, "key2": 200})

> key1 key2

 

# dict는 *이 2개이면 value 값이 매개변수에 전달됩니다.

# value 값을 전달할 때는 key이름과 매개변수의 이름이 같아야 합니다.

collection(**{"a": 100, "b": 200})

> 100 200

 

가변 매개변수와 키워드 가변 매개변수의 특징 : https://mimah.tistory.com/entry/Python-%EA%B0%80%EB%B3%80-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98-args%EC%99%80-%ED%82%A4%EC%9B%8C%EB%93%9C-%EA%B0%80%EB%B3%80-%EB%A7%A4%EA%B0%9C%EB%B3%80%EC%88%98-kwargs

 

가변 매개변수 :

- 1) 임의 개수의 인자를 받을 수 있다.

- 2) 가변 매개변수 사용시 매개변수를 아무것도 넣지 않아도 에러가 발생하지 않는다.

- 3) 가변 매개변수를 비가변 매개변수보다 뒤에 위치하는 것이 좋다.

(비가변 매개변수에는 입력되지 않고, 튜플의 형태로 가변 매개변수에만 입력이 되는 문제점이 발생할 수 있다.)

- 4) 가변 매개변수를 여러 개 사용하는 것도 불가능하다.)

 

키워드 가변 매개변수 :

- 1) dict의 'key' = 'value' 형태로 인수를 받을 수 있다.

- 2) 키워드 가변 매개변수 역시 사용시 매개변수를 아무것도 넣지 않아도 에러가 발생하지 않는다.

- 3) key를 제외한 value 만 매개변수에 대입할 수 없다.

- 4) 키워드 가변 매개변수를 여러 개 사용하는 것은 불가능하지만, 가변 매개변수와 혼용해서 사용하는 것은 가능하다.

 

=> 가변 매개변수

매개변수의 개수를 정하지 않고 사용하는 매개변수

매개변수를 만들 때 별(*)을 이용해서 이름을 설정합니다.

별(*)을 이용해서 매개변수를 설정하면 데이터 개수에 상관 없이 대입이 가능하며,

함수 내부에서는 매개변수들을 모아서 하나의 '튜플'을 만들어 냅니다.

 

매개변수를 만들 때 별별(**)을 추가하면 dict로 받아들이게 됩니다.

def merge(*arg):

for element in arg:

print(element)

 

merge(10)

merge(10, 20)

merge(10, 20, 30)

 

가변 매개변수 앞에 있는 매개변수에 대입할 때 매개변수 이름과 함께 대입하면 에러가 발생합니다.

가변 매개변수 뒤에 있는 매개변수에 대입할 때는 반드시 매개변수 이름과 함께 대입해야 합니다.

 

# 가변 매개변수 사용

# 매개변수 개수 상관없이 대입해서 호출 가능

# 함수 내부에서는 튜플

def merge(name, *arg):

for element in arg:

print(element)

 

merge("banseunghyeon", 10, 20, 30) # name에 banseunghyeon이 대입되고 나머지는 arg에 대입

merge(name="banseunghyeon", 10, 20, 30) # 이 구문은 에러

 

 

# 가변 매개변수 뒤의 데이터는 이름과 함께 호출

def merge(*arg, name):

for element in arg:

print(element)

 

merge(10, 20, 30, name="banseunghyeon")# name에 banseunghyeon이 대입되고 나머지는 arg에 대입

merge(10, 20, 30, "banseunghyeon") # 이 구문은 에러

 

=> 함수를 호출할 때 존재하지 않는 매개변수 이름을 이용해서 대입하면 dict로 받을 수 있습니다.

이 경우 dict는 가장 마지막 매개변수로 만들어야 합니다.

def merge(name, **kwarg):

for p in kwarg:

print(p, kwarg[p])

 

merge(name="banseunghyeon", job="student", gender="남자") # name은 존재하기 때문에 출력되지 않는다.

 

5) recursion(recursive call, 재귀 함수)

=> 함수가 자기 자신을 다시 호출하는 것

=> 함수의 수행이 종료되기 전에 자기 자신을 다시 호출하기 때문에 메모리 사용량도 늘어나고 속도도 느리지만 가독성이 우수

-> 주의해야 할 점은 반드시 종료되는 지점이 있어야 한다.

 

import functools

 

@functools.lru_cache()

를 사용하면 재귀함수를 사용하고도 피보나치 수열을 빠르게 계산할 수 있다.

 

# 피보나치 수열 구하기

# 첫번째와 두번째는 1, 그 이후부터는 이전 2개 항의 합

# 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89

 

# 피보나치 수열을 재귀로 구하는 함수

n = int(input("숫자를 입력하시오."))

def fibonacci(n:int) -> int:

if n == 1 or n == 2:

return 1

return fibonacci(n-1) + fibonacci(n-2)

 

result = fibonacci(n)

print(result)

 

# 재귀를 사용하지 않고 피보나치 수열 구하기

n = int(input("숫자를 입력하시오."))

def fibo(n:int) -> int:

sum = 1

n_1 = 1

n_2 = 1

for i in range(2, n):

sum = n_1 + n_2

n_1 = n_2

n_2 = sum

return sum

 

result = fibo(n)

print(result)

 

6) pass

=> 함수나 클래스의 내용을 나중에 작성하기 위해서 비워두는 것

def temp():

pass

 

7) 함수의 매개변수에 설명을 추가하는 것이 가능 -> 주석과 유사한 기능이다.

def 함수이름(매개변수이름:자료형) -> 리턴타입:

-> 매개변수의 자료형만 기재하는 경우 사용

 

def 함수이름(매개변수이름:'문자열') -> 리턴타입:

-> 매개변수에 관한 설명을 적고자 하는 경우 사용

def pan(score:'int >=0 and <=100' = 0) -> None:

 

8) 함수의 도움말 만들기

=> help를 했을 때 출력되는 문자열 만들기

=> 함수를 만들고 난 후 함수 바깥에서 함수.__doc__ 속성에 문자열을 대입해서 만들 수 있고,

함수를 만들 때 가장 상단에 문자열을 추가하면 help을 했을 때 출력이 됩니다.

 

9) 파이썬에서 함수는 일급 객체

=> 일급 객체

자료형이어야 합니다.

동적으로 생성이 가능해야 합니다.

변수에 대입이 가능해야 합니다.

함수의 매개변수로 사용이 가능해야 합니다.

함수에서 리턴할 수 있어야 합니다.

 

=> 함수를 변수에 대입

함수를 다른 변수에 대입해서 호출하는 이유는 다형성 때문입니다.

 

다형성(polymorphism): 동일한 메시지에 대하여 다르게 반응하는 성질이라고 하는데 동일한 코드가 상황에 따라 다른 함수 또는 메서드를 호출하는 것

 

def deanhypeboy():

print("딘의 하입보이")

 

def deangetup():

print("딘의 겟업")

 

delegate = deanhypeboy

delegate()

 

delegate = deangetup

delegate()

 

=> High Order Function(고위 함수)

함수를 매개변수로 받거나 함수를 리턴하는 함수

파이썬에서는 함수 안에서 함수를 생성하는 것이 가능

# 함수가 함수를 내부에 만들어서 리턴하면 고위 함수라고 합니다.

def outer():

def inner():

print("내부 함수")

return inner

 

# 함수를 호출해서 그 결과를 변수에 대입하고 그 변수를 통해서 함수를 호출합니다.

func = outer()

func()

 

=> lambda(람다) : 이름이 없는 한 줄 짜리 함수

-> 파이썬에서는 람다 함수에 한 줄만 적을 수 있다.

람다 함수 안에서는 변수를 생성할 수 없고, 할당문이나 while, try 등도 사용할 수 없다.

 

lambda 매개변수 나열 : 리턴할 내용

 

# 항상 1을 리턴하는 람다 함수

f = lambda : 1

 

# 2개의 숫자(x, y)를 받아서 합을 리턴하는 람다 함수

f = lambda x, y : x + y

 

주로 함수형 프로그래밍에서 함수의 매개변수로 이용

-> 기존의 함수처럼 static 영역에 생성되어 이름으로 저장하지 않고, 호출할 때 만들어지고 소멸된다.

ex. 기차 좌석 예매 : 누를 때만 생성되므로 낭비가 없다.

 

#python

'Python' 카테고리의 다른 글

05.OOP(1)  (0) 2023.08.17
04.Function(2)  (0) 2023.08.16
03.Control Statement  (0) 2023.08.05
02.Variable_Operator  (0) 2023.08.05
01.Python  (0) 2023.08.05