코딩하는 타코야끼

[Python] 5강_함수 본문

[T.I.L] : Today I Learned/Python

[Python] 5강_함수

가스오부시 2023. 4. 4. 20:19
728x90
반응형

1. 함수란

  • 함수란 입력변수와 출력변수간의 대응 관계를 정의한 것을 말한다.
  • 프로그램에서 함수란 하나의 작업, 기능, 동작을 처리하기 위한 사용자 정의 연산자라고 할 수 있다.
    • 함수는 값을 입력(Input)을 받아서 처리후 처리결과를 출력(Output)하는 일련의 과정을 정의한 것을 말한다.
    • 만들어진 함수는 동일한 작업이 필요할 때 마다 재사용될 수 있다.
    • 함수를 구현해 파이썬 실행환경에 등록하는 것을 함수를 정의(define)한다 라고 한다.
    • 정의된 함수를 사용하는 것을 함수를 호출(call)한다 라고 한다.
    • 파이썬에서 함수는 일급 시민 객체(First Class Citizen Object)이다.

 

🌓  일급 시민 객체란 – 변수에 할당할 수 있고, 함수의 입력값으로 전달할 수 있고, 함수의 반환 값으로 반환할 수 있는 객체를 말한다.

2. 함수 만들기

📍 함수의 정의

  • 새로운 함수를 만드는 것을 함수의 정의라고 한다.
  • 함수를 구현하고 그것을 파이썬 실행환경에 새로운 기능으로 등록하는 과정을 말한다.

📍 함수 구현

    • 함수의 선언부(Header) : 함수의 이름과 입력값을 받을 변수(Parameter, 매개변수)를 지정한다.
    • 함수의 구현부(Body) : 함수가 호출 되었을 때 실행할 실행문들을 순서대로 작성한다
    • 함수 선언 마지막에는 : 을 넣어 구현부와 구분한다.
    • Parameter(매개변수)는 argument(호출하는 곳에서 전달하는 함수의 입력값)를 받기 위한 변수로 0개 이상 선언할 수 있다.
    • 함수의 실행구문은 코드블록으로 들여쓰기로 블록을 묶어준다.
      • 들여쓰기는 보통 공백 4칸을 사용한다.
    • 함수의 처리 결과값이 있을 경우 return 구문을 넣고 없을 경우 return은 생략할 수 있다.
    • 함수이름 관례
      • 함수이름은 보통 동사형으로 만든다.
      • 모두 소문자로 하고 여러단어로 구성할 경우 각 단어들을 _로 연결한다. (변수와 동일)

# 함수 정의
def greeting(): #header(선언부) - parameter 가 없는 함수.
    # boody (구현부)
    print("안녕하세요.")
    print("반갑습니다.")
    # 반환값(return value) 없는 함수.
# 함수 호출 - []: 선택사항
# [반환값을 저장할 변수 = ] 함수이름([argument들, ])
# 함수이름()
greeting()
>>>
안녕하세요.
반값습니다.

📍 return value(반환값)

  • 함수가 호출받아 처리한 결과값으로 호출한 곳으로 반환하는 값이다.
  • 함수 구현부에 return [값] 구문을 사용해 반환한다.
    • return
      • 함수가 정상적으로 끝났고 호출한곳으로 돌아간다.
      • 보통은 함수 구현의 마지막에 넣지만 경우에 따라 중간에 올 수 있다.
    • return 반환값
      • 호출한 곳으로 값을 가지고 돌아간다. (반환한다)
      • 반환값이 없을 경우 None을 반환한다.
      • 함수에 return 구문이 없을 경우 마지막에 return None이 실행된다.
  • 여러개의 값을 return 하는 경우 자료구조로 묶어서 전달해야한다.
    • 함수는 한개의 값만 반환할 수 있다.
# return 값이 있는 함수
def greeting4(name):
    txt = f'{name}님 안녕하세요.\\n반갑습니다.'
    return txt # 호출한 곳으로(caller)로 txt변수값을 가지고 돌아가라.
    
--------

txt = greeting4('홍길동')
print(txt)
>>>
홍길동님 안녕하세요.
반갑습니다.
# return 값이 여러개인 함수.
def calculate(num1, num2):
    r1 = num1 + num2
    r2 = num1 - num2
    r3 = num1 * num2
    r4 = num1 / num2
    
    return r1, r2, r3 ,r4 # 튜플로 묶어서 반환.
#    return{'plus':r1, 'minus':r2, 'multuiply'r3, 'divide':r4} 딕셔너리 대입(참고)

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

result = calculate(10,20)
print(type(result))
print(result)
>>>
<class 'tuple'>
(30, -10, 200, 0.5)

📍 Parameter (매개변수)

  🌓  기본값이 있는 Parameter

  • 매개변수에 값을 대입하는 구문을 작성하면 호출할 때 argument 가 넘어오지 않으면 대입해놓은 기본값을 사용한다.
  • 함수 정의시 기본값 없는 매개변수, 있는 매개변수를 같이 선언할 수 있다.
    • 이때 기본값 없는 매개변수들을 선언하고 그 다음에 기본값 있는 매개변수들을 선언한다.
def print_info(name): # 매개변수에는 반드시 값이 대입되야 한다.
    print(f'이름: {name}')
    
--------------------

# 기본값이 있는 파라미터 -> caller가 argument를 전달하지 않으면 기본값을 대입해서 사용.
def print_info2(name=None):
    if name == None:
        print('이름이 없습니다.')
        return
    print(f'name: {name}')

🌓  Positional argument와 Keyword argument

  • Argument는 함수/메소드를 호출할 때 전달하는 입력값을 말한다.
    • Argument는 전달하는 값이고 Parameter는 그 값을 저장하는 변수
  • Positional argument
    • 함수 호출 할때 argument(전달인자)를 Parameter 순서에 맞춰 값을 넣어서 호출.
  • keyword argument
    • 함수 호출할 때 argument를 Parameter변수명 = 전달할값 형식으로 선언해서 어떤 parameter에 어떤 값을 전달할 것인지 지정해서 호출.
    • 순서와 상관없이 호출하는 것이 가능.
    • parameter가 많고 대부분 기본값이 있는 함수 호출 할 때 뒤 쪽에 선언된 parameter에만 값을 전달하고 싶을 경우 유용하다.
# positional argument 방식 호출
test_func(10,20,30,40,50,60,70)
>>>
10, 20, 30, 40, 50, 60, 70

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

#keyword argument 방식 호출
test_func(a=100, b=200, g=300, c=500, f=700, e=400, d=700)
>>>
100, 200, 500, 700, 400, 700, 300

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

def test_func2(a=0, b=0, c=0, d=0, e=0, f=0, g=0):
    print(a, b, c, d, e, f, g, sep=', ')

test_func2()
# 파라미터 g(마지막)의 값만 대입, 나머지는 default 값으로 호출
# 위치 기반
test_func2(0, 0, 0, 0, 0, 0, 100)
# keyword argument
test_func2(g=200)
>>>
0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 100
0, 0, 0, 0, 0, 0, 200

  🌓  가변인자 (Var args) 파라미터

  • 호출하는 쪽에서 argument로 0 ~ n개의 값을 나열해서 여러개의 값들을 전달하면 tuple이나 dictionary로 묶어서 받을 수있도록 선언하는 parameter
    • positial argument로 전달하는 것과 keyword argument로 전달되는 값을 받는 두가지 방식이 있다.
  • *변수명: positional argument를 개수와 상관없이 하나의 변수로 받을 수 있도록 선언하는 가변인자.
    • 전달된 값들은 tuple로 받아서 처리한다.
    • 관례적으로 변수명은 *args 를 사용한다.
  • **변수명: keyword argument를 개수와 상관없이 하나의 변수로 받을 수 있도록 선언하는 가변인자.
    • 전달된 값들은 dictionary로 받아서 처리한다.
    • 관례적으로 변수명은 **kwargs 를 사용한다.
  • 하나의 함수에 가변인자는 * 하나, ** 두개짜리 각각 한개씩만 선언할 수 있다.
  • 일반 parameter 들과 같이 사용할 경우 일반 parameter들을 먼저 선언하고 가변인자를 나중에 선연한다.
    • 두종류의 가변인자를 같이 선언할 때는 *변수명 가변인자를 먼저 선언한다.
def summation(nums): # 자료구조 (리스트, 튜플)
    # 누적합계 계산
    result = 0
    for i in nums:
        result += i
    return result
# 전달해 줘야 하는 값의 개수 가변(변경될 수 있다.)인 경우,
# 리스트나 튜플 같은 자료구조로 묶어서 전달.
r = summation([1,2])
print(r)
r= summation((1,2,3,4,5)) # 튜플은 소괄호
print(r)
>>>
3
15
def test_func(a, b, c, *args, **kwargs):
    print(a, b, c, args, kwargs)

lst = [100, 200, 300, 400]
dic = {'aaa':10, 'bbb':20, 'ccc':30}
# text_func() 호출 -> *args에 lst튜플을 **kwargs는 dic 딕셔너리의 값을 전달.
test_func(1,2,3, *lst, **dic)
# 가변인자 파라미터에 전달할 튜플/리스트 에 *를 딕셔너리에 **를 붙이면 positional args 와 keyword args로 변환되어 호출한다.
>>>
1 2 3 (100, 200, 300, 400) {'aaa': 10, 'bbb': 20, 'ccc': 30}

3. 변수의 유효범위

📍 전역변수 (global variable)

  • 함수 밖에 선언 된 변수
  • 모든 함수들이 공통적으로 사용할 수 있다.
  • 하나의 함수에서 값을 변경하면 그 변한 값이 모든 함수에 영향을 주기 때문에 함부로 변경하지 않는다.
  • 함수내에서 전역변수에 값을 대입하기 위해서는 global 키워드를 이용해 사용할 것을 미리 선언해야 한다.
    • global로 선언하지 않으면 이름이 동일한 지역변수가 된다.
    • 조회할 경우에는 상관없다.

📍 지역변수 (local variable)

  • 함수안에 선언된 변수
  • 선언된 그 함수 안에서만 사용할 수 있다.
name = '홍길동'  # 전역변수
address = '서울'

def func5():
    # 전역변수 name 의 값을 변경
    global name, address # 이 함수에서 name 변수를 사용하면(대입, 조회) 전역변수 name을 가리킨다. 고 선언
    name = '이순신' # 전역변수의 값 변경.

def func4():
    name = '이순신' # 지역변수 (함수안에 정의된 변수는 다 지역변수.)
    print('func4', name)

def func1():
    age= 10 # 함수안에 선언 및 초기화 -> 지역변수 -> 함수 안에서만 조회가능
    print(name, age)

def func2():
    age=30 # 지역변수
    print(name, age)
    
def func3():
    print(age)
func1() 
func5() # 전역변수 name 의 값을 변경
func1()
>>>
홍길동 10
이순신 10

4. 함수는 일급시민객체 => 함수는 값이다.

 📍 일급시민객체

  1. 변수에 대입 할 수 있다.
  2. 함수 호출할때 argument로 사용할 수 있다.
  3. 함수의 return 값으로 사용할 수 있다.

 📍 람다식/람다표현식 (Lambda Expression)

  • 함수를 하나의 식을 이용해서 정의할때 사용하는 표현식(구문).
  • 값을 입력받아서 간단한 처리한 결과를 반환하는 간단한 함수를 표현식으로 정의할 수 있다.
    • 처리결과를 return 하는 구문을 하나의 명령문으로 처리할 수 있을때 람다식을 사용할 수 있다. => return x + y
  • 구문

  • 명령문(구문)은 하나의 실행문만 가능하다.
  • 명령문(구문)이 처리한 결과를 리턴해준다.
  • 람다식은 함수의 매개변수로 함수를 전달하는 일회성 함수를 만들때 주로 사용한다.
def plus(n1,n2):
    return n1 + n2

plus2 = lambda n1, n2 : n1 + n2
--------
r= plus2(100,200)
print(r)
>>>
300

 📍 iterable 관련 함수에서 함수를 매개변수로 받아 처리하는 함수들

  🌓  sorted(iterable, reverse=False, key=None)

  • 정렬처리
  • 매개변수
    • reverse: True - 내림차순, False - 오름차순(기본)
    • key: 함수
      • Parameter로 iterable의 각 원소를 받는 함수.
      • 정렬을 할 때 iterable의 원소기준으로 정렬하는 것이 아니라 이 함수가 반환하는 값을 기준으로 정렬

🌓  filter(함수, Iterable)

  • Iterable의 원소들 중에서 특정 조건을 만족하는 원소들만 걸러주는 함수
  • 함수
    • 어떻게 걸러낼 것인지 조건을 정의. 매개변수 1개, 반환값 bool
    • 원소 하나 하나를 함수에 전달해 True를 반환하는 것만 반환
# result_gen = filter(func, nums)
nums = list(range(1,10))
result_gen = filter(lambda num : num%2==0, nums)
print(type(result_gen))
for r in result_gen:
    print(r)
>>>
<class 'filter'>
2
4
6
8

🌓  map(함수, Iterable)

  • Iterable의 원소들 하나 하나를 처리(변형)해서 그 결과를 반환
  • 함수
    • 원소들을 어떻게 처리할지 정의. 매개변수 1개. 반환값: 처리 결과
# mapping
nums = list(range(1,10))
for v in map(lambda num : num / 10, nums):
    print(v)
>>>
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9

🌓  filter/map 반환타입: generator 형태로 반환 된다. (리스트가 아님)


5. docstring

 📍 정의

  • 함수에 대한 설명
  • 함수의 구현부의 첫번째에 여러줄 문자열로 작성한다.
  • 함수 매개변수/리턴타입에 대한 힌트(주석)
def greeting(name:str, age:int, address:str = None) -> str:
    """
    함수에 대한 설명
    [parameter]:
        변수명: 데이터 타입 ~ 설명
        name: str ~ name 파라미터 설명
        age: int ~ age 파라미터 설명
        address: str = None - address 파라미터 설명.
    [return]:
        리턴값의 타입 - 리턴값에 대한 설명
        str - 인산말을 변환한다.
    [raise]:
        함수 실행도중 발생가능성이 있는 Exception타입을 설명.
        TypeError: 이름, 나이를 입력받지 못하면 발생.
    """
    return f'{address}에 사는 {age}세의 {name}님 안녕하세요.'

 

 📍 pass 키워드(예약어)

  • 빈 구현부를 만들때 사용
    • 코드블럭을 하는 일 없이 채울 때 사용
    • ... 을 대신 사용할 수 있다.
    def test1():
        pass
    
    def test2():
        pass
    
    def test3():
        pass
    
    def test5():
        ...
    
반응형