Python dict,tuple,function

정원·2022년 7월 1일

Python

목록 보기
3/7

22.07.01 dict,tuple,function

dict_basic

<script>
'''
* 사전 (Dictionary)

- 사전은 (key)(value)의 쌍을 저장하는 대용량의 자료구조.
- 사전은 타 언어에서는 Map이라고도 부르며 연관배열이라고도 부릅니다.
- 사전을 정의하는 기호는 {}이고, 괄호 안에 데이터를
Key : value 형태로 나열하여 저장합니다.
'''

students = {'멍멍이':'김철수', '야옹이':'박영희', '짹짹이':'홍길동'}
print(type(students)) # <class 'dict'>
print(len(students)) # 3

'''
- 사전에 사용되는 key값은 중복값을 가질 수 없고, 변경도 안됩니다.
- 반면에 value값은 중복을 허용하고, 데이터를 자유롭게 편집할 수도 있습니다.
- 사전 내부에 저장된 데이터를 검색할 때는 
인덱스 대신 key를 사용합니다.(시퀀스 자료형이 아니라서 인덱스가 없다.)
'''
# students[key]
print(students['멍멍이']) # 김철수
# print(students['메뚜기']) # KeyError

# in 키워드를 사용하여 key의 존재 유무를 파악할 수 있습니다.
print('멍멍이' in students) # True
</script>

dict_handle

<script>
'''
* 사전 내부 데이터 관리

- 사전은 변경 가능한 자료형이어서 실행 중에 데이터의 
추가, 삭제, 수정 등의 편집을 자유롭게 진행할 수 있습니다.
'''

# 데이터 추가하기(append()처럼 동작)
# 사전 내부에 존재하지 않는 (key)를 사용하여 데이터를 대입하면
# 데이터가 key:value 쌍으로 사전에 저장됩니다.
eng_kor = {'student':'학생','apple':'사과','book':'책'}

eng_kor['banana'] = '바나나' # 없는 키를 이용한 대입
print(eng_kor) # {'student': '학생', 'apple': '사과', 'book': '책', 'banana': '바나나'}

'''
* 사전에 데이터 수정
- 사전 내부에 이미 존재하는 key를 사용하여 새로운 데이터를 대입하면
해당 key값에 매핑되어 있는 value가 수정됩니다.
'''
eng_kor['book'] = '서적'
print(eng_kor) # {'student': '학생', 'apple': '사과', 'book': '서적', 'banana': '바나나'}

'''
- 사전의 key 목록과 value 목록을 따로따로 추출하고 싶다면
사전의 메서드 keys(), values()를 사용합니다.
'''
print(eng_kor.keys()) # dict_keys(['student', 'apple', 'book', 'banana'])
print(eng_kor.values()) # dict_values(['학생', '사과', '서적', '바나나'])
# 적절한 자료형 (list 등)으로 변환해서 사용 가능.

# 사전의 반복문 처리
# for ~ in 뒤에 사전 데이터를 적으면 key만 반복 순회합니다.
for k in eng_kor:
    print(f'{k} : {eng_kor[k]}')

'''
* 사전의 데이터 삭제(내장함수 del을 사용)
dle(사전이름[key])
key를 전달하면 같이 맵핑된 value도 함께 삭제됩니다.
'''
del(eng_kor['student'])
print(eng_kor) # {'apple': '사과', 'book': '서적', 'banana': '바나나'}

# 빈 사전 만들기
d = {}
d2 = dict()
</script>

food_manager dict 연습문제

<script>
'''
* 사전을 사용한 음식점 메뉴판 관리 프로그램.
- key: 음식명, value: 음식의 가격
'''
foods = {}

while True:
    print('\n\n======= 음식점 메뉴 관리 프로그램 =======')
    print('# 1. 신규 메뉴 등록하기')
    print('# 2. 메뉴판 전체보기')
    print('# 3. 프로그램 종료')
    print('==============================================')
    menu = int(input('# 메뉴 입력: '))

    if menu == 1:
        '''
        1. 메뉴명을 입력받아 해당 메뉴가 사전에 이미 존재한다면
         이미 등록된 메뉴라고 얘기해 주세요.
        2. 사전에 존재하지 않는 메뉴라면 가격을 입력받아
        key:value 쌍으로 맵핑하여 사전에 저장하세요.
        '''
        name = input('메뉴명: ')
        if name not in foods:
            price = input('가격:')
            foods[name] = price
            print(f'{name}이(가) 등록 완료 되었습니다.')        
        else:
            print(f'{name}은(는) 이미 존재합니다.')
    elif menu == 2:
        '''
        - 만약 2번을 선택했는데, 메뉴가 하나도 등록되어 있지 않다면
        먼저 등록하라고 메인 메뉴로 돌려보내 주세요.

        - 사전에 등록된 메뉴명과 가격을 전부 출력해 주세요.
        ex) 짜장면 : 4000원
            탕수육 : 18000원
            짬뽕 : 7000...
        -----------------------------------------

        메뉴판 전체 출력 후 메뉴를 새롭게 입력받아 주세요.
        ex (1. 수정 | 2. 삭제 | 3. 나가기)
        새로운 메뉴를 입력받아서 수정과 삭제를 진행 해 주세요.
        # 수정 -> 가격을 변경할 메뉴의 이름을 먼저 입력받고
        해당 이름이 사전에 존재한다면 수정할 가격을 새롭게 입력받고
        수정을 진행 해 주세요. 이름이 없다면 없다고 출력.
        # 삭제 -> 삭제할 메뉴명을 입력받아서 삭제를 진행.
         이름이 없으면 없다고 출력.
        # 나가기 -> 메인메뉴로 나가시면 됩니다.
        '''
        if len(foods) != 0:
            print('\n======= 메뉴판 =======')
            for m in foods:
                print(f'{m} : {foods[m]}원')
            print('===================================\n')

            print('# 1. 수정 | 2. 삭제 | 3. 나가기')
            select = input('> ')
            if select == '1':
                print('가격을 변경할 메뉴를 입력해주세요.')
                name = input('>')
                if name in foods:
                    new_price = input('가격:')
                    foods[name] = new_price
                    print('수정이 완료되었습니다.')
                else:
                    print(f'{name}이(가) 메뉴에 없습니다.')    
            elif select == '2':
                name = input('삭제할 메뉴:')
                if name in foods:
                    del(foods[name])
                    print('삭제가 완료되었습니다.')
                else:
                    print(f'{name}이(가) 메뉴에 없습니다.')
            elif select == '3':
                print('메인 메뉴로 돌아갑니다.')
                # continue -> 굳이 안넣어도 된다...!!
            else:
                print('메뉴를 잘못 입력하셨습니다. 메인 메뉴로 돌아갑니다.')        
        else:
            print('메뉴가 등록되어 있지 않습니다.')
            # continue -> 굳이 안써도 while True가 시작됨.
    elif menu == 3:
        '''
        ("# 프로그램을 종료하시겠습니까? [Y / N]")
        프로그램 종료 여부를 한번 더 물어봐 주세요.
        만약 y 이외의 값이 들어온다면 종료 의지가 없다고 판단하고
        종료를 취소하도록 하겠습니다.
        (소문자 y도 인정입니다.)
        '''
        answer = input('프로그램을 종료하시겠습니까? [Y / N] : ')
        if answer.lower() == 'Y':
            print('프로그램을 종료합니다.')
            break
        else:
            print('프로그램 종료를 취소합니다.')
    else:
        print('메뉴를 잘못 입력하셨습니다.')
</script>

tuple

<script>
'''
* 튜플 (tuple)

- 튜플은 값의 집합이라는 측면에서는 리스트와 유사하지만
값을 한 번 저장한 후에는 내부 요소의 편집이 불가능합니다.(고정 리스트)
- 튜플은 상수 리스트라고도 부르며 ()를 사용하여 표현합니다.
- 튜플도 문자열과 리스트와 마찬가지로 시퀀스 자료형입니다.(인덱스 O)
'''
points = (87, 97, 23, 45, 100)
print(type(points)) # <class 'tuple'>

sum = 0
for p in points:
    sum += p
print(f'총점:{sum}점, 평균: {sum / len(points):0.1f}점')

# 튜플을 만들 때는 ()를 생략할 수 있습니다.
tu = 1, 3, 5, 7, 9
print(type(tu)) # <class 'tuple'>

# 튜플은 리스트와 마찬가지로 unpackiging이 가능합니다.
n1, n2, n3, n4, n5 = tu
print(n1, n2, n3, n4, n5) # 1 3 5 7 9

# 튜플로 가능한 문법 (내부 요소 값을 바꾸지 않는 행위)
print(tu[2]) # 인덱싱
print(tu[1:3]) # (3, 5) 슬라이싱
print(tu + (10, 11)) # 튜플 + 튜플 (1, 3, 5, 7, 9, 10, 11)
print(tu * 2) # 튜플 2 (1, 3, 5, 7, 9, 1, 3, 5, 7, 9)

# 튜플로 불가능한 문법(내부 요소 값을 바꾸는 행위)
# tu[2] = 19 # 수정
# tu.append(10) 추가
# del(tu[0]) 삭제

# tuple이 지원하는 메서드는 index(), count().

'''
* 튜플을 사용하는 이유

- 튜플로 가능한 일은 리스트로도 모두 가능합니다.
 리스트는 튜플에 비해 요소를 편집하는 행위도 가능합니다.
- 결국, 리스트는 튜플의 기능을 모두 포괄하는 더 큰 범위의
타입이지만, 튜플을 사용해야 하는 이유는 존재합니다.

1. 비용의 차이: 리스트는 변경의 가능성을 항상 대비해야 하기 때문에
더 많은 메모리 공간을 차지하고, 속도도 그만큼 느립니다.
이에 비해, 튜플은 값의 집합만 표현할 뿐, 바뀔 일이 없으므로
내부 구조가 더 단순하고 속도도 더 빠릅니다.

2. 데이터 안정성: 리스트는 실수로 내부 데이터가 의도치 않게
 바뀔 위험이 있지만, 튜플은 한 번 정해지면 바뀔 수가 없기 때문에
 실수할 위험이 적습니다.
데이터베이스나 네트워크에서 얻은 데이터는 단순히 참조만 하면
될 뿐, 편집할 일이 많지 않습니다.
그렇기 때문에 리스트로 관리하는 것보다 튜플로 처리하는 것이
안전합니다.

3. 리스트와 상호 변경이 자유로움: 리스트와 튜플은
값 변경 가능성 여부만 다를 뿐, 구조가 상당히 유사합니다.
리스트를 튜플로 변환할 때는 내장함수 tuple()을 사용하고,
튜플을 리스트로 변환할 때는 내장함수 list()를 사용합니다.
'''
p = [2,3,4,5,6] # list

p = tuple(p) # tuple로 변환

p = list(p) # list로 변환
</script>

set_basic

<script>
'''
* 집합(set)

- 집합은 여러 값들의 모임이며, 저장 순서가 보장되지 않고
중복값을 저장을 허용하지 않습니다.
- 집합은 사전과 마찬가지로 {}로 표현하지만, key:value 쌍이 아닌, 
데이터가 하나씩 들어간다는 점이 사전과는 다릅니다.

- set() 함소는 공집합을 만들기도 하며, 다른 컬렉션 자료형을 집합 형태로 변환할 수도 있다.

# [] , list()  빈 list 생성
tuple() 빈 tuple 생성(내장함수만 지원)
{}, dict() 빈 dict 생성
set()set 생성(내장함수만 지원)
'''

names = {'홍길동', '김철수', '박영희', '고길동', '홍길동'}
print(type(names)) # <class 'set'>
print(names) # {'고길동', '김철수', '박영희', '홍길동'}

for x in names:
    if x == '김철수':
        print(x)
        break

# 내장함수 set()
s = set()
print(type(s)) # <class 'set'>
print(s) # set()

s1 = 'programming'
print(set(s1)) # {'p', 'o', 'r', 'a', 'i', 'm', 'n', 'g'} 순서X,중복X
print(list(s1)) # ['p', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g'] 순서O,중복O
print(tuple(s1)) # ('p', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', 'n', 'g')

'''
- 집합은 변경 가능한 자료형이어서 언제든지 데이터를 
편집할 수 있습니다.

- 집합에 요소를 추가할 때는 add() 메서드를 사용하고,
제거할 때는 remove()를 사용합니다.
'''
asia = {'korea', 'china', 'japan'}
print(asia)

asia.add('thailand')
asia.add('china')
asia.remove('japan')
print(asia)

# 집합의 결합은 update() 메서드를 사용합니다.(덧셈,곱셈 연산X)
asia2 = {'singapore', 'indonesia', 'korea'}
# print(asia + asia2) 에러
asia.update(asia2)
print(asia)
</script>

set_operator

<script>
'''
* 집합의 연산

1. 합집합(|): 두 집합의 전체 요소들의 모음(중복 제거)
2. 교집합(&): 두 집합의 중복을 배제한 공통 요소들의 모음.
3. 차집합(-): 왼쪽 집합에서 오른쪽 집합 요소를 제거
4. 배타적 차집합(^): 합집합 - 교집합
5. 부분집합(<=): 왼쪽 집합이 오른쪽 집합의 부분집합인지를 검사
'''

A = {2, 4, 6, 8, 10, 12}
B = {3, 6, 9, 12, 15}
print('교집합:', A&B) # {12, 6}
print('합집합:', A|B) # {2, 3, 4, 6, 8, 9, 10, 12, 15}
print('차집합(A-B):', A-B) # {8, 2, 10, 4}
print('차집합(B-A):', B-A) # {9, 3, 15}
print('배타적 차집합:', A^B) # {2, 3, 4, 8, 9, 10, 15}

C = {4, 8, 12}
print(C <= A) # True
print(C <= B) # False
</script>

set_operator 문제

<script>
'''
- 서로 다른 정수가 담긴 두 개의 리스트를 비교하여
li 안에 있는 정수가 li2에도 담겨 있다면 그 정수를 배제하시고
서로 겹치지 않는 정수만 담긴 새로운 리스트를 생성해 보세요.
'''
li = [1, 2, 3, 4, 5, 6, 7]
li2 = [1, 3, 8, 4, 5, 7, 101]

li3 = []

# list의 문법
for n in li:
    if n not in li2:
        li3.append(n)

for n in li2:
    if n not in li:
        li3.append(n)
li3.sort()
print(li3)

# set 문법
result = set(li) ^ set(li2)
print(result)
</script>

function_basic

<script>
'''
* 함수(function)

- 함수는 지속적으로 사용되는 코드 블록에 이름을 붙여놓은 형태입니다.
- 함수는 한 번 정의해 두면 지정된 함수 이름을 통해
언제든지 해당 코드 블록을 실행할 수 있습니다.
- 함수를 정의할 때 사용하는 키워드는 def 입니다.
- 정의해 놓은 함수를 사용하는 것을 호출(call)이라고 부릅니다.
- 파이썬에서는 함수를 호출하려면 반드시 호출문보다 상단부에
함수를 먼저 정의해야 합니다.
'''

# 함수의 정의(1~end까지의 누적합을 구하는 로직)
def calc_sum(end):
    sum = 0
    for n in range(1, end+1):
        sum+= n
    return sum

# 함수의 호출
print('1~100까지의 누적합:', calc_sum(100))

'''
* 인수, 매개변수(arguments)

- 인수는 함수를 호출할 때 함수 실행에 필요한 값들을 전달하는
매개체 역할을 하며, 그렇기 때문에 매개변수(parameter)라고도 부릅니다.
- 인수의 개수는 제한이 없어 많은 값을 함수에 전달할 수도 있고
하나도 전달하지 않을 수 있습니다.
- 파이썬의 경우에는 데이터 타입을 작성하지 않기 때문에
이 함수를 처음 사용하는 사람도 인수 이름만 보고 무슨 값을
전달해야 할 지 의미를 알기 쉽게 지정하는 것이 좋습니다.
'''

'''
* 연습

1. 인수를 정수형태로 시작값(start), 끝값(end)을 입력받아
 반복문으로 start부터 end까지의 누적 총합을 구하는 함수를 정의하세요.

2. 함수 이름은 calc_rangesum으로 정의하세요.
ex) calc_rangesum(3, 7) -> 3부터 7까지의 누적합을 구해와야 함.

3. 출력예시: "x~y까지의 누적합: z"
사용자에게 입력받은 값을 함수로 전달해서 값을 출력해 보세요.
'''

def calc_rangesum(start, end):
    if start > end:
        start, end = end, start
        
    total = 0
    for n in range(start, end+1):
        total += n
    return total

n1 = int(input('정수1:'))
n2 = int(input('정수2:'))
print(f'{n1}~{n2}까지의 누적합:{calc_rangesum(n1,n2)}')

'''
* 반환값 (return value)

- 반환값이란 함수를 호출한 곳으로 함수의 최종 실행 결과를 전달하는 값입니다.
- 인수는 여러 개 존재할 수 있지만, 반환값은 언제나 하나만 존재해야 합니다.
- 모든 함수가 반환값이 있는 것은 아닙니다.
함수 실행 후 딱히 반환할 값이 없다면 return을 생략할 수 있습니다.
'''
def add(n1, n2):
    return n1 + n2

result = add(10, 5)
# 리턴이 있는 함수는 다른 함수의 매개값으로도 사용이 가능합니다.
print(add(add(5,7), add(9,8))) # add(12,17)

def operate_all(n1, n2):
    return n1 + n2, n1 - n2 # tuple로 return
    # return n1 - n2 return은 한번만 가능 

def multi(n1, n2):
    result = n1 * n2
    print(f'{n1} X {n2} = {result}')

abc = multi(9, 6) # return없는 메서드는 변수에 담아도 None이 온다.
print(abc) # None(null)
</script>

function_map

<script>
'''
* 내장함수 map()

- map()은 첫번째 인수로 함수를 지정하고, 
두 번째 인수로 리스트를 지정하면 해당 리스트 내부 요소값을 일괄적으로
첫번째 인수로 지정한 함수에 인수로 전달합니다.
'''

# 3개의 숫자 중 최대값을 판별하여 리턴하는 함수를 정의
def max_of_three(n1, n2, n3):
    if n1 > n2:
        if n1 > n3:
            return n1
        else:
            return n3
    else:
        if n2 > n3:
            return n2
        else:
            return n3
'''
n1 = int(input('정수1:'))
n2 = int(input('정수2:'))
n3 = int(input('정수3:'))
'''
# map(함수,리스트) -> 리스트 내부 요소를 함수로 일괄 전달.
# 여래 개의 데이터를 한 번에 다른 형태로 변환하기 위해 사용.

# 입력받은 3개의 값을 split()으로 잘라서 리스트로 변경 후 int 내장함수를 이용해서 str을 int로 변경
n1, n2, n3 = map(int, input('정수 3개를 공백으로 구분해서 입력하세요:').split())
print('최대값:', max_of_three(n1, n2, n3))

def triple_square(number):
    return number ** 3

li = [2, 4, 6, 8, 10]

'''
triple_square(li[0])
triple_square(li[1])
triple_square(li[2])
...
'''

# li의 요소들을 하나씩 triple_square에 전달 후 
# map 함수가 리턴하는 객체를 list로 변경해서 result에 저장
result = list(map(triple_square, li))
</script>

func_args_default

<script>
'''
* 인수의 기본값

- 파이썬에서는 인수의 기본값을 설정하여, 자주 바뀌지 않는
매개값은 기본값으로 처리할 수 있도록 해 줍니다.
'''
def calc_stepsum(begin, end, step=1): # step 기본값 지정
    sum = 0
    for n in range(begin, end+1, step):
        sum += n
    return sum

print(calc_stepsum(1, 10)) # step은 기본값으로 설정

# 기본값 2개 이상 지정할때
# 기본값이 지정된 인수를 오른쪽으로 몰아 주셔야 합니다.
def calc_sum(end , begin=0, step=1):
    sum = 0
    for n in range(begin, end+1, step):
        sum += n
        return sum

print(calc_sum(100)) # (begin=0 , end, step=1) 이렇게 쓰면 100이 begin으로 들어간다. 
</script>

func_args_keyword

<script>
'''
* 키워드 인수(keyword argument)

- 인수의 개수가 많아지면 인수의 순서를 파악하기 어렵고 
함수를 호출할 때 전달할 값의 위치를 헷갈릴 가능성이 높아집니다.

ex) def signpu_user(id, pw, name, addr, email ....)

- 파이썬에서는 순서와 무관하게 인수를 전달할 수 있는 방법을 제공하여
인수의 이름을 직접 지정하여 값을 전달하는 키워드 인수 방식을 제공합니다.
'''

def calc_sum(begin, end, step):
    sum = 0
    for n in range(begin, end+1, step):
        sum += n
    return sum

# 일반적인 함수 호출(위치 인수 방식 -> positional argument)
calc_sum(3, 7, 1)

# 키워드 인수 사용 (순서 상관 X )
print(calc_sum(end=7, step=1, begin=3))

# 위치 인수와 키워드 인수의 혼합 사용 시에는
# 무조건 위치 인수가 앞에 와야합니다.
print(calc_sum(3, step=1, end=7))
# print(calc_sum(end=7, 3, 1)) 에러. 
# print(calc_sum(3, 1, end=7)) 에러. end에 값이 두개 들어감.
# print(calc_sum(3, end=7, 1)) 에러.

print(3, 6, 9, sep='->', end='!') # sep,end가 키워드 인수
</script>

func_var_args

<script>
'''
* 위치 가변 인수

- 함수를 호출할 때는 함수 정의시에 지정한 인수의 개수만큼 값을 전달해야 합니다.
- 하지만 가변 인수를 사용하면 하나의 인수로 여러 개의 값을
받아서 처리할 수 있습니다.
- 위치 가변인수를 함수 정의부에서 인수를 선언할때 
인수 앞에 * 기호를 붙여 선언하며, 이런 경우에 여러 개의 데이터를 
튜플로 묶어서 함수 내부로 전달합니다.
'''

def calc_total(*nums):
    print(type(nums)) # <class 'tuple'>
    total = 0
    for n in nums:
        total += n
    return total

print(calc_total(5,6,8,2,11,54,356)) 

def calc_poins(*poins, name):
    print(f'{name} 학생의 성적 계산 ')

    total = 0
    for p in poins:
        total += p
    return total / len(poins)

# 가변 인수와 일반 인수를 동시에 사용할 때에는 
# 일반 인수를 반드시 키워드 인수 방식으로 전달하셔야 합니다.

# result = calc_poins(97, 100, 60, 20, '김철수') # 에러. keyword-only argument: 'name'
result = calc_poins(97, 100, 60, 20, name='김철수')
print(f'평균: {result}점')


'''
* 연습 - n개의 정수를 전달받아 가장 큰 숫자를 찾아서
 리턴하는 함수를 작성 하세요. (get_max)
 사용자에게 map()를 사용해서 여러 개의 값을 하나의 input()으로
 입력 받은 후 get_max()에게 전달해서 가장 큰 값을 리턴받으세요.
 입력받을 값은 5개로 하겠습니다.
'''
def get_max(*nums):
    max = nums[0]

    for n in nums:
        if n < max:
            max = n
    return max
    
n1, n2, n3, n4, n5 = map(int, input('정수 5개를 공백을 기준으로 작성하세요:').split())
print(get_max(n1, n2, n3, n4, n5))
</script>

0개의 댓글