본문 바로가기

배운 책들 정리/혼자 공부하는 파이썬

혼자 공부하는 파이썬 5,6 - 함수 고급, 예외 처리

5장 함수

5-3. 함수 고급

1) 튜플, 람다

* 튜플

- 리스트는 요소 변경이 가능하지만 튜플은 요소 변경이 불가능

- 그리고 튜플은 ()를 사용 (리스트는 [] 사용하지만)

- 사용법은 리스트와 같음

- []은 변경 되지만 ()은 변경 불가능

 

# 튜플 = 리스트와 거의 유사
tuple_a = (1,2,3)

# 튜플의 원소에 접근하여 출력
print(tuple_a[0])  # 출력 결과: 1
print(tuple_a[1])  # 출력 결과: 2
print(tuple_a[2])  # 출력 결과: 3

tuple_a[0] = 10  # 튜플은 원소의 값 변경이 불가능하므로 에러 발생

# 튜플은 immutable(불변)한 자료형으로, 한 번 생성된 후에는 원소의 값을 변경할 수 없음
# 따라서 tuple_a[0] = 10과 같이 원소의 값을 변경하려고 하면 에러가 발생함

 

# 소괄호가 없는 튜플
[a,b] = [1,2]
(c,d) = (3,4)
print(a,b,c,d)

e = 1,2,3,4
print(e)
print(type(e))

f,g,h = 5,6,7
print(f,g,h)

a,b = 1,2
print("교환하기 전의 a,b의 값 : {},{}".format(a,b))
a,b = b,a
print("교환하기 전의 a,b의 값 : {},{}".format(a,b))

# 튜플과 함수
def test():
  return (1,2)
a,b = test()
print(a,b)

# 튜플을 리턴하는 함수
for i, j in enumerate([1,2,3,4]):
  print("인덱스: {}, 값: {}".format(i,j))

# 딕셔너리 # 동일한 결과값
for i, j in {0:1,1:2,2:3,3:4}.items():
  print("인덱스: {}, 값: {}".format(i,j))

a,b= 63, 30
print(a//b)
print(a%b)

c,d =divmod(a,b)
print(c,d)

 

 

2) 람다

- 함수를 간단하고 쉽게 선언하는 방법 (일회용)

 

# 람다
def repeatten(fx):
    for i in range(10): # 10번 반복하는 for 루프
        fx() # 인자로 받은 함수 fx()를 호출

def printhi():
    print("Hi")

repeatten(printhi) # printhi 함수를 repeatten 함수에 인자로 전달하여 10번 "Hi"를 출력하도록 동작

 

3) 튜플과 람다 비교

 

# map & filter (함수, 리스트)
def power(item):
    return item**2

def under_3(item):
    return item < 3

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

output_map = map(power, list_a) # map 함수를 사용하여 list_a의 각 요소에 power 함수를 적용하여 새로운 리스트를 생성
print(output_map)
print(list(output_map)) # map 함수를 사용하여 생성된 리스트를 출력

output_filter = filter(under_3, list_a) # filter 함수를 사용하여 list_a의 각 요소에 under_3 함수를 적용하여 조건을 만족하는 요소만으로 이루어진 새로운 리스트를 생성
print(output_filter)
print(list(output_filter)) # filter 함수를 사용하여 생성된 리스트를 출력
# 람다로 변경
power = lambda x: x**2  # 람다 함수를 사용하여 x의 제곱을 반환하는 함수를 정의
under_3 = lambda x: x<3  # 람다 함수를 사용하여 x가 3보다 작은지를 확인하는 함수를 정의

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

output_map = map(power, list_a)  # map 함수를 사용하여 list_a의 각 요소에 power 함수를 적용하여 새로운 리스트를 생성
print(output_map)
print(list(output_map))  # map 함수를 사용하여 생성된 리스트를 출력

output_filter = filter(under_3, list_a)  # filter 함수를 사용하여 list_a의 각 요소에 under_3 함수를 적용하여 조건을 만족하는 요소만으로 이루어진 새로운 리스트를 생성
print(output_filter)
print(list(output_filter))  # filter 함수를 사용하여 생성된 리스트를 출력

# 더 단축시키기
list_a = [1, 2, 3, 4, 5]

output_map = map(lambda x: x**2, list_a)  # map 함수를 사용하여 list_a의 각 요소에 람다 함수를 적용하여 새로운 리스트를 생성
print(output_map)
print(list(output_map))  # map 함수를 사용하여 생성된 리스트를 출력

output_filter = filter(lambda x: x<3, list_a)  # filter 함수를 사용하여 list_a의 각 요소에 람다 함수를 적용하여 조건을 만족하는 요소만으로 이루어진 새로운 리스트를 생성
print(output_filter)
print(list(output_filter))  # filter 함수를 사용하여 생성된 리스트를 출력

 

 

 

* 파일 저장 및 with 코드 (자동으로 파일이 닫히는)

 

 

# 파일 처리
# 파일 열고 닫기
file = open("basic.txt","w")
# 텍스트 쓰기
file.write("안녕 파이썬 재밌니")
# 파일 닫기
file.close()



# 키워드 with 로 변경
# 파일 열고 닫기
with open("basic.txt","w")as file:
  # 파일에 텍스트를 씁니다.
  file.write("0418 비내리는 날")

# 텍스트 읽기
with open("basic.txt","r")as file:
  con = file.read()
print(con)

 

 

* csv 텍스트 파일을 만든 것을 토대로 반복문 실행하기 // bmi 구분하기

 

# 텍스트 한 줄씩 읽기
# csv 텍스트 파일 만들기

import random

hg = list("가나다라마바사아자차카타파하")

# info.txt 파일을 쓰기 모드로 열기
with open("info.txt", "w") as file:
  # 1000번 반복하여 텍스트 파일에 데이터 쓰기
  for i in range(1000):
    # 이름, 몸무게, 키를 랜덤하게 생성
    name = random.choice(hg) + random.choice(hg) + random.choice(hg)
    weight = random.randrange(40,150)
    height = random.randrange(130,210)
    
    # 텍스트 파일에 데이터 쓰기
    file.write("{}, {}, {}\n".format(name, weight, height))
# 데이터를 한 줄씩 읽기 - 변수 새로 만들기
with open("info.txt","r") as file:
  for line in file:
    (name, weight, height) = line.strip().split(", ") # line = 이름, 몸무게,키
    if (not name) or (not weight) or (not height):
      continue
    bmi = int(weight) / ((int(height)/100) ** 2)
    result = ""
    if 25 <= bmi:
      result = "과체중"
    elif 18.5 <= bmi:
      result = "정상체중"
    else:
      result = "저체중"
    
    print("\n".join(["이름:{}",
                "몸무게: {}",
                "키:{}",
                "bmi:{}",
                "결과:{}"]).format(name,weight,height,bmi,result))
    print()

# 파일 만들 때 공백을 안 넣어서 공백 제거가 의미가 없어졌던 부분임

 

 

* 키워드 매개변수 활용

 

# 리스트 함수를 딕셔너리에서 사용
books = [{"제목":"A",
          "가격":10000},
         {"제목":"B",
          "가격":20000},
         {"제목":"C",
          "가격":30000}]
def price(book):
  return book["가격"]
print(min(books,key = price))
print(max(books,key = price))

 

 

# 람다로 변경
books = [{"제목":"A",
          "가격":10000},
         {"제목":"B",
          "가격":20000},
         {"제목":"C",
          "가격":30000}]
print(min(books,key = lambda book: book["가격"]))
print(max(books,key = lambda book: book["가격"]))

 

 

* 오름차순, 내림차순

 

# 리스트 정렬
# 오름차순
a = [1,25,34,7,15]
a.sort()
print(a)

# 리스트 정렬
# 내림차순
a = [1,25,34,7,15]
a.sort(reverse=True)
print(a)
# sort 적용
books = [{"제목":"A",
          "가격":10000},
         {"제목":"B",
          "가격":20000},
         {"제목":"C",
          "가격":30000}]
books.sort(key = lambda book: book["가격"],reverse= True )
print(books)

 

 

4) 확인문제 352p

* 1번 (숫자를 문자열로 출력)

 

numbers = [1,2,3,4,5,6]

# map 함수를 사용하여 numbers 리스트의 원소들을 문자열로 변환
# map 함수는 원소들을 지정된 함수(str 함수)에 적용하여 새로운 리스트를 반환
# 하지만 map 함수는 iterator 객체를 반환하므로, 바로 출력하면 주소 값이 출력됨
print(map(str,numbers))  # 출력 결과: <map object at [주소값]>

# map 함수를 사용하여 numbers 리스트의 원소들을 문자열로 변환하여 새로운 리스트를 생성
# list 함수를 사용하여 iterator 객체를 리스트로 변환하여 출력
print(list(map(str,numbers)))  # 출력 결과: ['1', '2', '3', '4', '5', '6']

# map 함수를 사용하여 numbers 리스트의 원소들을 문자열로 변환하고, "::" 문자열로 연결하여 출력
# join 함수를 사용하여 리스트의 원소들을 지정된 문자열로 연결
print("::".join(map(str,numbers)))  # 출력 결과: '1::2::3::4::5::6'

 

 

* 2번

 

# 확인 문제 1번 352p
numbers = list(range(1,10+1))


print("# 홀수만 추출하기")
print(list(filter(lambda x: x%2 != 0,numbers)))
print()

print("# 3이상, 7 미만 추출하기")
print(list(filter(lambda x: 3<=x<7,numbers)))
print()

print("# 제곱하기")
print(list(filter(lambda x: x**2<50,numbers)))

 

 

5) 도전문제 354p (하노이의 탑)

* 1번

 

# 도전 문제 1
def hanoi(n, from_tower, to_tower, aux_tower):
    if n == 1:
        print(from_tower, "->", to_tower) # 원판이 1개일 경우에는 그냥 직접 옮김
    else:
        hanoi(n-1, from_tower, aux_tower, to_tower) # 원판 n-1개를 보조 기둥으로 옮김
        print(from_tower, "->", to_tower) # 원판 n을 목적 기둥으로 옮김
        hanoi(n-1, aux_tower, to_tower, from_tower) # 보조 기둥에 있는 n-1개의 원판을 목적 기둥으로 옮김

n = int(input("원판의 개수를 입력해주세요:"))  # 원판 개수 입력 받음
hanoi(n, "A", "B", "C")  # A 기둥에서 C 기둥으로 원판을 옮기는 과정 출력

 

 

* 2번

 

# 도전 문제 2
def hanoi(n, from_tower, to_tower, aux_tower):
    if n == 1:
        print(from_tower, "->", to_tower) # 원판이 1개일 경우에는 그냥 직접 옮김
        return 1 # 이동 횟수 1 추가
    else:
        count = 0 # 이동 횟수를 카운트하는 변수
        count += hanoi(n-1, from_tower, aux_tower, to_tower) # 원판 n-1개를 보조 기둥으로 옮기는 과정의 이동 횟수를 추가
        print(from_tower, "->", to_tower) # 원판 n을 목적 기둥으로 옮김
        count += 1 # 이동 횟수 1 추가
        count += hanoi(n-1, aux_tower, to_tower, from_tower) # 보조 기둥에 있는 n-1개의 원판을 목적 기둥으로 옮기는 과정의 이동 횟수를 추가
        return count # 전체 이동 횟수 반환

n = int(input("원판의 개수를 입력해주세요:"))  # 원판 개수 입력 받음
total_count = hanoi(n, "A", "B", "C")  # A 기둥에서 C 기둥으로 원판을 옮기는 과정 출력 및 이동 횟수 반환
print("총 이동 횟수:", total_count) # 총 이동 횟수 출력

* 스택 : 기본 자료형이 저장된 곳.   // 기본자료형이란 : 문자열, 숫자, 불

 

import matplotlib.pyplot as plt

# 원판을 옮기는 함수
def hanoi(n, from_tower, to_tower, aux_tower):
    if n == 1:
        print(from_tower, "->", to_tower)
        plt.plot([from_tower, to_tower], [0, 1], 'ro-') # 이동 경로를 시각화
    else:
        hanoi(n-1, from_tower, aux_tower, to_tower)
        print(from_tower, "->", to_tower)
        plt.plot([from_tower, to_tower], [0, 1], 'ro-') # 이동 경로를 시각화
        hanoi(n-1, aux_tower, to_tower, from_tower)

# 원판 개수 입력 받음
n = int(input("원판의 개수를 입력해주세요:"))

# 그래프 설정
fig = plt.figure(figsize=(5, 5))
plt.axis('off')
plt.xlim([-1, 3])
plt.ylim([-0.2, 1.2])

# 타이틀
plt.title(f'Hanoi Tower (n={n})')

# 초기 위치 표시
for i in range(n):
    plt.text(i, 0, str(i+1), ha='center', va='center')

# 하노이 탑 알고리즘 실행 및 시각화
hanoi(n, 'A', 'C', 'B')

# 그래프 출력
plt.show()

 

6장 예외 처리

1. 구문 오류와 예외

1) 조건문 예외 처리 // 한정적으로 경우를 걸 경우에만 해당 됨

 

# 오류 수정
print("리스트 불러보자")
list_z = [1,2,3]
list_z[0]

# 예외 상황 만들기 - 숫자로 변환할 수 없는 값을 입력한 경우
no = input("정수 입력>")
no = int(no)
print("원의 반지름", no)
print("원의 둘레", 2*3.14*no)
print("원의 넓이", 3.14*no*no)
# 조건문으로 예외 처리
no = input("정수 입력>")
if no.isdigit(): # 숫자로 변환할 수 있는 값을 입력한 경우
  no = int(no)
  print("원의 반지름", no)
  print("원의 둘레", 2*3.14*no)
  print("원의 넓이", 3.14*no*no)
else: # 나머지 = 숫자로 변환할 수 있는 값을 입력하지 않은 경우
  print("숫자가 입력되지 않았습니다. 정수를 입력하세요")

 

 

2) try except

 

# try except 구문으로 예외 처리
try:
  no = input("정수 입력>")
  no = int(no)
  print("원의 반지름", no)
  print("원의 둘레", 2*3.14*no)
  print("원의 넓이", 3.14*no*no)
except:
  print("숫자가 아닙니다. 정수만 입력해주세요")
# try except 구문으로 예외 처리
try:
  no = input("정수 입력>")
  no = int(no)
  print("원의 반지름", no)
  print("원의 둘레", 2*3.14*no)
  print("원의 넓이", 3.14*no*no)
except:
  pass

 

3) try except else // finally 사용

 

# try except else 구문으로 예외 처리
try:
  no = input("정수 입력>")
  no = int(no)
except:
  print("정수를 입력해주시겠어요")
else:
  print("원의 반지름", no)
  print("원의 둘레", 2*3.14*no)
  print("원의 넓이", 3.14*no*no)
# try except else finally 구문으로 예외처리
try:
  no = input("정수 입력>")
  no = int(no)
except:
  print("정수를 입력해주시겠어요")
else:
  print("원의 반지름", no)
  print("원의 둘레", 2*3.14*no)
  print("원의 넓이", 3.14*no*no)
finally:
  print("프로그램은 어떻게든 종료가 되었어요")

 

 

* 핵심

1) 중요한 구문 조합 (finally)

try + except 구문

try + except + finally 구문

try +finally 구문 

 

* 링크 (직접 글 쓴 당사자만 확인 가능 // 계정 이동해서 확인하기)

https://colab.research.google.com/drive/1RoC4AJZc5zyeYfZ-6gCFQ7HlGBBHUSKf?usp=sharing 

 

Google Colaboratory Notebook

Run, share, and edit Python notebooks

colab.research.google.com

 

* 오늘의 링크

파이썬 코드 시각화 링크.

 

Python Tutor code visualizer: Visualize code in Python, JavaScript, C, C++, and Java

Please wait ... your code is running (up to 10 seconds) Write code in Python 3.6 C (gcc 9.3, C17 + GNU) C++ (g++ 9.3, C++20 + GNU) Java 8 JavaScript ES6 ------ Python 2.7 [unsupported] Visualize Execution hide exited frames [default] show all frames (Pytho

pythontutor.com

 

 

728x90
반응형
LIST