파이썬/파이썬 이론

7. Python_Function

잘잔디 2023. 4. 13. 17:47

함수

  • 반복적인 코드의 양을 줄여 유지보수성을 높여준다.
  • snake case로 이름 짓는 것을 추천
  • argument = 인수(함수 호출부) , parameter = 인자(=매개변수, 함수 정의부) , return = 반환값
  • 파이썬 함수는 overloading이 안된다. = 같은 함수이름을 가지지만 시그니처(매개변수)는 달라서 구분하는 방식.
  • class에 있어서 객체를 통해 호출되면 method이고( ~.으로 호출하면 method이다.)
  • class 밖에 있으면 Function이다.(list, length, print …)
  • 기본값 설정이 가능하다. 인수(호출부에서 들어오는놈)가 비었다면 기본값을 사용한다. def get_grade(score = 60): pass와 같으면 기본값 = 60, 기본값을 갖는 parameter는 parameter들 중 가장 뒤에 선언되어야 한다.

함수 인자 선언방식

  1. 위치 키워드 = 위치로 혹은 키워드로 전달될 수 있는 인자(매개변수의 기본 형태) 기본값이 없는 argument(위치 방식),기본값이 있는 argument(키워드 방식) 둘 다 된다는 소리
  2. 위치 전용 = /문자를 기준으로 좌측에 위치한 인자를 말함
  3. 키워드 전용 = * 문자를 기준으로 우측에 위치한 인자를 말함
  4. 가변 위치 = 위치 매개변수 외에 추가적인 위치 매개변수를 개수에 상관없이 받을 수 있다.(변수명 앞에 *를 붙여 표기
  5. 가변 키워드 = 키워드 매개변수 외에 추가적인 키워드 매개변수를 개수에 상관없이 받을 수 있습니다.(변수명 앞에 **를 붙여 표기) = 딕셔너리 형태로 만들어준다.

def isPrime(num):
    primes = [False, False] + [True]*(num-1)
    for i in range(2, num+1):
        if primes[i]:
            for _ in range(i * 2, num+1, i):
                primes[_] = False
    return primes[num]

get = int(input('찾는 범위: '))
lst = [_ for _ in range(2, get) if isPrime(_)]
count = 0
for _ in lst:
    count+=1
    print(_,end=" ")
    if count%7 == 0:
        print()

 

def get_grade(score, std_num, name = "민병창"): # 1. 기본 방식. positional + keyword
    """
    숫자로된 점수를 넣으시면 학점의 결과를 반환합니다.
    """
    print("{},{}의 성적을 확인합니다.".format(std_num,name))
    if 85 <= score <= 100:
        return 'A'
    elif 70 <= score <= 84:
        return 'B'
    elif 55 <= score <= 69:
        return "C"
    elif 40 <= score <= 54:
        return "D"
    elif 0 <= score <= 39:
        return "E"

get_grade(100,std_num = 200) # score는 positional하게, std_num 은 keyword형식으로, name은 default값으로 잘 들어간다.

def add_number(number1,/,number2): # 2.positional only(number1은 positional only로 설정됨. / 기준 왼쪽)
    '''
    숫자 number1 과 숫자 number2를 전달 받아 더한 값을 반환합니다.
    '''
    return number1 + number2
print(add_number(10,number2 = 20)) #애는 정상실행
print(add_number(number1 = 10,number2 = 20)) # 얘는 TypeError발생.

def string_line(str_value,/,str_len=70,*,sep="#"):#3,4.왼쪽 positional only ,가운데 1.기본값 오른쪽keyword only
    '''
    str_value는 가운데 오는 텍스트입니다.
    str_len은 텍스트의 설정할 길이입니다.
    sep는 구분선을 그을 떄 쓰는 문자입니다.
    '''
    print(str_value.center(str_len, sep))

string_line('구분',str_len = 50, sep = "*")

def hell(a,b,*lst): # 4.가변 positional 방식(*args로 사용)
    '''
    doc string 입니다.
    '''
    print(a,b)
    print(lst)
hell(1,2,3,4,5,6,7,8,9)

print(hell.__doc__)

def functional_name(positional, positional2,*arguments, keyword = 1, **keywordarguments):
    pass

def test_func2(a="a",b="b",**kargs): # 5.가변 keyword (**args로 사용)
    print(a,b)
    print(type(kargs))
    print(kargs)

test_func2(a="ab",b="bc",key="value",key2 = "value2")

 

def plus_ten(n):
    return n+10
print(plus_ten(70))

def to_celsius(fahrenheit):
    '''
    화씨온도를 받으면 섭씨온도로 반환해줍니다
    '''
    return (fahrenheit-32)*5/9
to_celsius(70)

def odd_even(n):
    '''number가 짝수면 "짝수",홀수면 "홀수" 반환'''
    if type(n) == type(10) and n>0:
        return "짝수" * (number%2 == 0) or "홀수"
    else: 
        return None

print(odd_even.__doc__)
print(odd_even(-1))
print(odd_even(9))
print(odd_even("가"))

def check_leap_year(year):
    #return "평년" * (year %100 == 0 and year%400 != 0) or "윤년" * (year%4==0) or "평년"
    if year % 4 == 0 and (year %100 != 0 or y % 400 == 0):
        return "윤년"
    else:
        return "평년"

print(check_leap_year(2004))
print(check_leap_year(2000))
print(check_leap_year(1900))

def days(year,month):

    if month in [1,3,5,7,8,10,12]:
        return 31
    elif month in [4,6,9,11]:
        return 30
    else:
        if year % 4 == 0 and (year %100 != 0 or year % 400 == 0):
            return 29
        else:
            return 28

print(days(1900,11))
print(days(2004,10))
print(days(1900,2))
print(days(2000,2))

x = 10
y = 3
def get_quotient_remainder(x,y):
    return x//y , x%y

quitient,remainder = get_quotient_remainder(x,y)
print(f'목: {quitient}, 나머지: {remainder}')

변수의 범위(Scope)

  1. 전역변수 = 가장 바깥 영역에서 선언한 변수(스크립트 전체에서 접근 가능하다.)
  • 지역범위 내에서 global 범위에 접근(단순조회 x)(변경)하고 싶을 때 global 키워드로 접근이 가능하다.
  1. 지역변수 = 함수 바디와 같이 지역내에서 선언된 변수(해당 지역 내에서만 접근이 가능하다.)
  • 안쪽 함수에서 바깥쪽 함수에 선언된 변수에 접근하고 싶을 때 nonlocal 키워드로 접근이 가능하다.
  • nonlocal은 제일 가까운 바깥 변수를 매칭한다.
  • 그렇기에 함수마다 다른 이름의 변수를 사용하는게 좋다(겹친다고 nonlocal로 다 가져올 수 있는 게 아니기 때문)

함수에서 변수를 호출하면!

  • 지역 영역 -> 전역 영역 -> 내장 영역 순으로 해당하는 변수를 확인한다. (내장영역 = 파이썬 자체에서 정의한 이름공간)

def level1():
    message = "This is level 1."
    def level2():
        nonlocal message
        message = "Thsi is level 2."
    level2()
    print(message)
level1() # level 2가 출력되는 것을 보아 nonlocal의 사용방식을 알 수 있다.

람다 Lambda

  • 호출될 때 값이 구해지는 하나의 표현식이다. (이름이 없는 인라인 함수이다)
  • 사용법 = lambda parameters : expression
  • 변수에 람다식을 저장(할당)할 수 있다.
  • 변수 없이 식 한 줄로 표현 가능(두줄로 쓰거나 ;로 줄을 늘리는게 불가능하다 = 새 변수를 만들 수 없다.)
  • (lambda x,y=10 : x+y)(1)은 가능하다. 다만 변수가 필요한 경우는 def를 쓰는 게 낫다.

조건 표현식과 람다

  • True일떄 값 if 조건식 else False일 때 값
  • if와 else가 반드시 둘 다 와야 하며 중첩 가능하다.
  • 조건 표현식은 1줄이기 때문에 람다와 궁합이 좋다.
  • map 또한 함수를 여러 인수들에게 적용해 주므로 람다와 궁합이 좋다.

# 람다 예제
x = lambda a,b : a+b
print(x(1,3))
print((lambda a,b : a+b)(5,6))

#조건 표현식 예제 (조건 표현식 2번 사용한 예제)

score = 90
"A" if 90<score<=100 else "B" if 80<score else "C"
# 람다와 map의 조합
a = [_ for _ in range(1,6)]
b = [_ for _ in range(2,11,2)]
print(list(map(lambda x,y : x*y, a, b))) #a의 5개 값과 b의 5개 값을 map으로묶어 lambda함수를 한번에 적용했다.

람다 filter()

  • 람다와 filter() 함수를 같이 쓸 때 사용
  • 함수의 반환 값이 True 일때만 해당 요소를 가져온다. list comprehension으로도 표현이 가능한 방식이다.
  • 사실 list comprehension이 더 보기 좋다.

a = [3,2,8,22,10,7,0,11,9,9]
list(filter(lambda x: x%3 ==0 and 0<x<10,a))