상세 컨텐츠

본문 제목

함수에 대한 기초 지식

Python

by techbard 2024. 10. 28. 10:07

본문

반응형

 

특성

1. def 키워드를 사용해서 정의한다.
2. 리턴 타입에 대한 정의가 필요없다.
3. return 이 없으면 None을 반환한다.

 

# return true if any number is even inside a list
# 리스트 안에 짝수가 하나라도 있으면 True, 하나도 없으면 False 반환

def check_even_list(nums):
    for n in nums:
        if n % 2 == 0:
            return True
        else:
            pass

    return False

# 초보자들은 else 문이 if와 짝을 이루어야 한다고 생각하지만
# logic을 잘 생각해 보면 그렇지 않음을 알 수 있다.
# 모든 리턴 값이 들여쓰기 될 필요는 없다.

print(f'[1, 3, 5] -> {check_even_list([1, 3, 5])}')
print(f'[1, 2, 5] -> {check_even_list([1, 2, 5])}')
print(f'[1, 5, 2] -> {check_even_list([1, 5, 2])}')

# 결과
[1, 3, 5] -> False
[1, 2, 5] -> True
[1, 5, 2] -> True

 

# 3개의 임의 리스트 중 하나를 선택해 맞췄는지 판단
# 함수를 여러 개 만들고 그들을 하나로 상호작용하게 한다.

# game_list = [' ', 'O', ' ']

from random import shuffle

# 1) shuffle 함수는 아무것도 반환하지 않는다.
# 2) 따라서, init_guess가 변경되어 반환하지 않아도 된다.
# 3) 그러나, 명시적인 반환으로 구현하는게 명확하다.
def shuffle_list(init_guess):
    shuffle(init_guess)
    return init_guess

def player_guess():
    guess = ''

    while guess not in ['0', '1', '2']:
        guess = input('Pick a number: 0, 1 or 2')
    return int(guess)

def check_guess(mixed_list, guess_idx):
    if mixed_list[guess_idx] == 'O':
        print('Correct!')
    else:
        print('Wrong guess!')
        print(mixed_list)

init_guess = [' ', 'O', ' ']
mixed_list = shuffle_list(init_guess)
player_guess = player_guess()
check_guess(mixed_list, player_guess)

# 결과
Pick a number: 0, 1 or 21
Wrong guess!
[' ', ' ', 'O']

 

## 숫자를 받아 그것이 모두 짝수이면 그중 작은 수를 반환
## 숫자중 홀수가 포함되면 그중 큰 수를 반환

## 쉬운 구현
def lesser_of_two_evens(num1, num2):
    if num1 % 2 == 0 and num2 % 2 == 0:
        return min(num1, num2)
    else:
        return max(num1, num2)


print(lesser_of_two_evens(2, 4))
print(lesser_of_two_evens(1, 2))

# 결과
2
2

## 나의 솔루션
def my_lesser_of_two_evens(*args):
    is_all_even = False
    for n in args:
        if n % 2 == 0:
            is_all_even = True
        else:
            is_all_even = False
            break

    if is_all_even:
        return min(args)
    else:
        return max(args)


print(my_lesser_of_two_evens(2, 4))
print(my_lesser_of_two_evens(1, 2))
print(my_lesser_of_two_evens(1, 2, 3))

# 결과
2
2
3

# PEP 8, de-facto code style guide for Python
# PEP 8에 의거 최상위 함수와 클래스는 다른 코드와 두 줄씩 띄어 쓴다.
# 클래스 내의 메서드는 한 줄씩 띄어 쓴다.

 

## ANIMAL CRACKERS: Write a function takes a two-word string and
## returns True if both words begin with same letter.
##
## animal_crackers('Levelheaded Llama') --> True
## animal_crackers('Crazy Kangaroo') --> False


## 솔루션 버전
def animal_cracers(strs):
    word_list = strs.lower().split()
    first_word = word_list[0]
    second_word = word_list[1]
    return first_word[0] == second_word[0]


print(animal_cracers('Levelheaded Llama'))
print(animal_cracers('Crazy Kangaroo'))

## 나의 버전
## (솔루션 버전의 해법을 보니 이런 식은 나중에 기억하기 어려워서 좋은 구현은 아니다.
def my_animal_crackers(strs):
    word_list = strs.split()
    if word_list[0][0] == word_list[1][0]:
        return True
    else:
        return False

print(my_animal_crackers('Levelheaded Llama'))
print(my_animal_crackers('Crazy Kangaroo'))

# 결과
True
False
True
False

 

## Given a list of ints, return True if the array contains a 3 next to a 3 somewhere.
## 3 3이 연달아 존재하면 True 반환
##
## has_33([1, 3, 3) -> True
## has_33([1, 3, 1, 3]) -> False
## has_33([3, 1, 3) -> False
##
## 나는 그냥 같은 숫자가 두 번 연속으로 나오면 True로 구현했다.


def my_has_33(num_list):
    for idx in range(0, len(num_list)-1):
        current_num = num_list[idx]
        next_num = num_list[idx + 1]
        if current_num == next_num:
            return True
    return False


result1 = my_has_33([1, 3, 3])
result2 = my_has_33([1, 3, 1, 3])
result3 = my_has_33([3, 1, 3])
result4 = my_has_33([3, 1, 1, 1, 3])
print(result1, result2, result3, result4)

# 결과
True False False True

 

## SPY GAME: Write a function that takes in a list of integers and returns
## True if it contains 007 in order.
##
## 0, 0, 7이 이어지지 않아도 순서대로 존재하면 True 반환
## 7, 0, 0은 False 반환


def spy_game(nums):
    code = [0, 0, 7, 'x']
    # [0, 7, 'x']
    # [7, 'x']
    # ['x]  length = 1

    for n in nums:
        if n == code[0]:
            code.pop(0)
    return len(code) == 1


result1 = spy_game([1, 2, 3, 0, 0, 7, 5])
result2 = spy_game([1, 0, 2, 4, 0, 5, 7])
result3 = spy_game([1, 7, 2, 0, 4, 5, 0])
print(result1, result2, result3)

# 결과
True True False

 

# 대소문자 글자수 카운트
text = 'Hello Mr. Rogers, how are you this fine Tuesday?'

def up_low(text):
    uppercase, lowercase = 0, 0
    for char in text:
        if char.isupper():
            uppercase += 1
        elif char.islower():
            lowercase += 1
        else:
            pass # is '?' is entered.
    return (uppercase, lowercase)

print(f'Original String: {text}')
print(f'No. of Upper case characters: {up_low(text)[0]}')
print(f'No. of Lower case characters: {up_low(text)[1]}')

# 결과
Original String: Hello Mr. Rogers, how are you this fine Tuesday?
No. of Upper case characters: 4
No. of Lower case characters: 33

 

# 고유한 리스트 요소만 반환

def uniqe_list(lst):
    d = dict()

    for l in lst:
        if d.get(l, None) == None:
            d.setdefault(l, 1)
        else:
            d[l] += 1

    return d.items()

sample_list = [1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5]

print(f'Original list: {sample_list}')
print(uniqe_list((sample_list)))

# 결과
Original list: [1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 5]
dict_items([(1, 4), (2, 2), (3, 4), (4, 1), (5, 1)])

 

  • 생성

# 인자 (argument)와 리턴 (return)이 없는 간단한 함수의 생성

def myFunc():print('It\'s my function.')
myFunc()
결과)It's my function.
# 사용하기 전에 정의가 되어 있어야 한다.myFunc()
def myFunc():print('It\'s my function.')
결과)NameError: name 'myFunc' is not defined
# return 이 없으면 무조건 None 을 반환한다.def mySecondFunc():pass
result = mySecondFunc()print(result)
결과)None
# 함수는 return 과 함께 종료하며 return 뒤의 반환값을 호출한 곳으로 반환한다.def myThirdFunc():return True
result = myThirdFunc()print(result)
결과)True
# 함수 인자는 pass by reference로 동작함l = [1, 2, 3]
def byRefExam(lists):    lists.append('4')    return
byRefExam(l)
print(l)
결과)[1, 2, 3, '4']
  • 함수의 인자

# 기본값을 가진 인자의 사용

def useDefaultArgs(age, name = 'sally'):print(name, age)
useDefaultArgs(16)
결과)sally 16

# 기본값 인자가 순서상 가장 먼저 나오면 안 된다.

def useDefaultArgs(name = 'sally', age):print(name, age)
useDefaultArgs(16)
결과)SyntaxError: non-default argument follows default argument
# 인자가 일치하지 않으면 에러가 발생한다.def useDefaultArgs(name = 'sally'):print(name, age)
useDefaultArgs(16)
결과)NameError: name 'useDefaultArgument' is not defined
# 인자에 열거형 데이터 사용하기def useDefaultArgs(mylist):print('length: ' + str(len(mylist)))
l = ['1', '2']
useDefaultArgs(l)
결과)length: 2
# 열거형 데이터를 기본값 인자로 사용하기def addItems(items, base = []):for item in items:base.append(item)return base
addItems((1, 2, 3))result = addItems((4, 5, 6))
print(result)
결과)[1, 2, 3, 4, 5, 6]
# 인자의 유무를 None 플래그로 판단해 초기화하면 의도대로 구현할 수 있다.def addItems(items, base = None):if base is None:base = []for item in items:base.append(item)return base
addItems((1, 2, 3))result = addItems((4, 5, 6))
print(result)
결과)[4, 5, 6]
# 가변 인자의 사용def varArgs(*args):print(args)
varArgs('I am ')varArgs('I am ', ' a variable argument')
결과)('I am ',)('I am ', ' a variable argument')
# 가변 인자는 튜플로 알아서 할당된다.def listArgs(one, two, *args):    print(one, two, args)
print(listArgs(1, 2, 3, 4, 5))
결과)1 2 (3, 4, 5)
# 가변인자로 할당된 튜플 꺼내쓰기

def listArgs(one, two, *args):

    print(one, two)    for n in args:        print(n)
print(listArgs(1, 2, 3, 4, 5))
결과)1 2345None

 

# 익명함수와 가변 인자의 사용

add2 = lambda x, y: x + y
x = [2, 3]
print(add2(*x))
결과)5

 

# 가변 키워드 인자의 사용 #1def varArgs(**kwargs):print(kwargs)
varArgs(name = 'mike')
결과){'name': 'mike'}

# 가변 키워드 인자의 사용 #2

def keywordArgs(**kwargs):    print(kwargs['one'], kwargs['two'], kwargs['three'])
keywordArgs(one = 1, two = 2, three = 3)
결과)1 2 3
# 가변 인자의 혼합 사용def mixedVarArgs(a, b, *args, **kwargs):print('a, b:' , (a, b))print('args: ' , args)print('kwargs: ' , kwargs)
mixedVarArgs(1, 2, 3, 4, e = 0, f = 99)
결과)a, b: (1, 2)args:  (3, 4)kwargs:  {'e': 0, 'f': 99}

 

# 튜플 가변인자와 dict 가변 인자에 대한 보충 설명http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/
 

How to use *args and **kwargs in Python - SaltyCrane Blog

How to use *args and **kwargs in Python Or, How to use variable length argument lists in Python. The special syntax, *args and **kwargs in function definitions is used to pass a variable number of arguments to a function. The single asterisk form (*args) i

www.saltycrane.com

 

# 키워드 가변 인자의 사용
# 키워드 가변 인자는 결국 dict 인자를 받겠다는 것

def check_fruits(**kwargs):
    if 'fruit' in kwargs:
        print(f'My fruit of choice is {kwargs['fruit']}.')
    else:
        print('I did not find any fruit here.')

check_fruits(fruit = 'banana')
check_fruits(doing = 'bike')
# 여러 인자를 넣어도 하나만 처리 외부 라이브러리에 많이 사용
check_fruits(fruit = 'banana', veggie = 'sweet potato')

# 결과
My fruit of choice is banana.
I did not find any fruit here.
My fruit of choice is banana.

 

 

 

 

  • 함수의 범위

# 코드 경로에 따라 변수를 참조하지 못하는 경우가 발생한다.

def innerFunc(text):if text is 'x':output = 'x is here'return output
print(innerFunc('x'))print(innerFunc('y'))
결과)x is hereUnboundLocalError: local variable 'output' referenced before assignment
  • 함수도 컨테이너에 담을 수 있나?
# 함수를 리스트에 넣고 호출하기def fa():print('function a.')
def fb():print('function b.')
l = [fa, fb]
l[0]()l[1]()
결과)function a.function b.
# 함수를 튜플에 넣고 호출하기def fa():print('function a.')
def fb():print('function b.')
l = (fa, fb)
l[0]()l[1]()
결과)function a.function b.
# 함수를 사전에 넣고 호출하기 #1def fa():print('function a.')
def fb():print('function b.')
d = {'first':fa, 'second':fb}
for k, v in d.items():v()
결과)function b.function a. # 순서 유지는 안 된다.

# 함수를 사전에 넣고 호출하기 #2

def fa():print('function a.')
def fb():print('function b.')
d = {0:fa, 1:fb} # key에 정수를 직접 넣을 수도 있다.
for i in range(0, len(d), 1):d[i]()
결과)function a.function b. # 순서를 가지는 정수를 발생시켜서 키로 쓰기 때문에 순서가 유지된다.
  • 재귀함수

# 재귀함수의 활용예 1

def explode(word):    if len(word) <= 1:        return word    else:        return word[0] + ' ' + explode(word[1:])
print(explode('hello'))
결과)h e l l o

# 재귀함수의 활용예 2

def removeDups(word):    if len(word) <= 1:        return word    elif word[0] == word[1]:        return removeDups(word[1:])    else:        return word[0] + removeDups(word[1:])
print(removeDups('aabbbc'))
결과)abc
  • 함수의 중첩
# 함수를 중첩하면 보다 간단한 로직을 만들 수 있다.def plusDouble(f, s):    def Double(n):        return n * n    return Double(f) + Double(s)
print(plusDouble(1, 2))
결과)5
# 두 함수의 결과를 한 번에 리턴할 수 있으며 분리된 함수를 한 곳에 모을 수 있다.def displayFE(s):    def First(s):        return s[0:1]    def End(s):        return s[-1:]    return First(s) + End(s)
print(displayFE('masterpiece'))
결과)me
# 함수를 변수에 할당할 수 있는 성질을 이용한 중첩 함수의 이용def create_adder(first):    def add(first, second):        return first + second        def adder(second):        return add(first, second)    return adder
addTo2 = create_adder(2)
print(addTo2(3))
결과)5
# 람다함수를 이용해서 두 함수의 결과를 합칠 수 있다.def displayFE(s):    x = (lambda s: s[0:1])(s)    y = (lambda s: s[-1:])(s)    return x + y
print(displayFE('masterpiece'))
결과)me
  • 람다함수

# 익명 함수를 사용할 수 있다.

l = [5, 10, 20]result = filter(lambda x : x > 5, l)print(list(result))
결과)[10, 20]

 

# 함수 자체를 변수에 저장할 수 있어서 람다함수와 결합할 수 있다.

sq = lambda x: x*x
print(sq(2))
결과)4
# 람다함수는 함수 객체를 생성하기 때문에 그 자체로도 map 함수의 인자가 될 수 있다.sq = lambda x: x*x
print(list(map(sq, [1, 2, 3])))
결과)[1, 4, 9]
# 람다함수를 실행하면 함수 객체만 반환한다.print(lambda n : n * 2)
결과)<function <lambda> at 0x000000000203CBF8>
# 함수를 변수에 저장하지 않고도 인자를 전달할 수 있다.print((lambda n : n * n)(2))
결과)4
# 람다함수는 함수이므로 인자를 주어 호출해야 결과를 얻을 수 있다.l = ['Oh', 'My', 'God']
a = lambda x: [c[0] for c in x]
print(''.join(a(l)))
결과)OMG
# map() 내장함수를 이용한 첫글자 추출l = ['Oh', 'My', 'God']
a = lambda x: x[0]
print(list(map(a, l)))
결과)['O', 'M', 'G']
# 시퀸스 형을 람다함수에 인자로 주어야 할때는 map 함수를 사용한다. map 함수는 개별 시퀀스 형 데이터에 대해서 각각 어떤 처리를 할 때 사용한다.print(list(map(lambda n: n+1, [1, 2, 3])))
결과)[2, 3, 4]
# 축약어 만들기 - map과 lambda 함수 사용words = ['as', 'soon', 'as', 'possible']
print(''.join(map(lambda s: s[0].upper(), words)))
결과)ASAP

# 축약어 만들기 - 시퀀스 순회로 스트링 조합

words = ['as', 'soon', 'as', 'possible']result = ''for w in words:    result += w[0].upper()print(result)
결과)ASAP

# 축약어 만들기 - 리스트 컴프리헨션 사용

words = ['as', 'soon', 'as', 'possible']
print(''.join([x[0].upper() for x in words]))
결과)ASAP
# 시퀀스 형 데이터를 누적식으로 처리할 때는 functools 모듈의 reduce() 함수를 사용한다.import functools
n = range(1, 11)sum = functools.reduce(lambda x, y: x+y, n)print(sum)
결과)55
# Flatten a listimport functools
words = ['this', 'is', 'a', 'new', 'world']print(functools.reduce(str.__add__, words))
결과)thisisanewworld

시퀀스 타입이 스트링일 때 처리

import functools
words = ['this', 'is', 'a', 'new', 'world']print(functools.reduce(lambda x, y: x+y, words))
결과)thisisanewworld
# 시퀀스 타입이 정수일 때 처리import functools
nums = range(1, 10)print(functools.reduce(lambda x, y: x+y, nums))
결과)55
# reduce() 함수에서 다음의 동작은 허용되지 않는다.import functools
words = ['this', 'is', 'a', 'new', 'world']print(functools.reduce(lambda x, y: len(x) + len(y), words))
결과)TypeError: object of type 'int' has no len()
# 직접 인자로 주면 동작한다.import functools
print(functools.reduce(lambda x, y: len(x) + len(y), ['hello', 'apple']))
결과)10
# 인자로 주어진 스트링 길이의 합을 구하고 싶을때print(sum(map(len, words)))
결과)15

 

# 시퀀스 형 데이터의 참, 거짓에 따라 참만 골라내고 싶을때는 filter() 함수를 사용한다.n = range(1, 11)print(list(filter(lambda x: x % 2 == 0, n)))
결과)[2, 4, 6, 8, 10]
  • 함수에서 Generator 사용

yield 키워드

def inclusiveRange(start, stop, step = 1):    i = start    while i <= stop:        yield i        i += step
for i in inclusiveRange(0, 10, 1):    print(i, end = ' ')
결과)0 1 2 3 4 5 6 7 8 9 10 
  • 비정형 함수 인자의 처리

default argument 에러

def inclusiveRange(start = 0, stop, step = 1):    i = start    while i <= stop:        yield i        i += step
# for i in inclusiveRange(0, 10, 1):for i in inclusiveRange(25):    print(i, end = ' ')
결과)SyntaxError: non-default argument follows default argument
# 함수 인자에 대한 직접 처리def inclusiveRange(*args):    lenArgs = len(args)    if lenArgs < 1: raise TypeError('more argument is needed.')    elif lenArgs == 1:        start = 0        stop = args[0]        step = 1    elif lenArgs == 2:        (start, stop) = args        step = 1    elif lenArgs == 3:        (start, stop, step) = args    else: raise TypeError('not admitted more than 3 arguments: '.format(lenArgs))
    i = start    while i <= stop:        yield i        i += step
for i in inclusiveRange(1, 25):    print(i, end = ' ')
결과)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 

 

# 함수 인자에 대한 자동 처리

 

def show(a, b, c):

print(a, b ,c)

 

ls = list(range(1, 4))

 

show(*(ls))

 

# 결과

1 2 3

 

반응형

관련글 더보기

댓글 영역