Learn & Record

Python(메소드, 사용자정의함수, 모듈, 지역변수_전역변수, 외부모듈, 리스트메소드, 내부모듈, 연습문제) 본문

Dev/Python

Python(메소드, 사용자정의함수, 모듈, 지역변수_전역변수, 외부모듈, 리스트메소드, 내부모듈, 연습문제)

Walker_ 2024. 2. 28. 17:24

1. 메소드

 - 메소드 method란 특정 객체 object가 가지고 있는 함수 function을 의미

 - 함수는 독립적으로 호출할 수 있지만, 메소드는 특정 객체를 통해서만 호출할 수 있음

 - 함수와 다르게 메소드는 특정 객체 소속이어서, 메소드를 호출하려면

 - 특정 객체를 통해서만 호출 가능

# 1. 문자열 메소드
# 문자열 str을 처리하기 위해 많은 메소드를 제공

# 1) format()
# 정렬 옵션
# < : 지정된 공간 내에서 왼쪽 정렬
# > : 지정된 공간 내에서 오른쪽 정렬
# ^ : 지정된 공간 내에서 가운데 정렬

# 10d는 10자리의 필드 폭을 의미
print("10자리 폭 왼쪽 정렬 '{:<10d}'".format(123)) # 10자리 폭 왼쪽 정렬 '123    '

# 2) count()
# 문자열 내부에 포함된 특정 문자열의 개수를 반환하는 메소드

print()
s = '내가 그린 기린 그림은 목 긴 기린 그림이고, 네가 그린 기린 그림은 목 짧은 기린 그림이다'
print(s.count('기린')) # 4

# 인덱스를 지정해서 범위를 지정할 수 있음
s = 'best of best'
print(s.count('best', 5)) # 1 / 인덱스 5번부터 검색

# 마이너스 인덱스를 사용할 수 있음
s = 'best of best'
print(s.count('best', -7)) # 1 / -7 인덱스인 o 부터 검색

# 3) find()
# 문자열 내부에 포함된 특정 문자열을 찾고자 할 때 사용
# 찾고자 하는 문자열이 있으면 그 문자열이 처음으로 나온 위치 즉 인덱스 index를 반환
print()
s = 'apple'
print(s.find('p')) # 1

# 찾는 문자열이 없는 경우 -1 반환
s = 'apple'
print(s.find('z')) # -1

if s.find('z') == -1:
    print(s)

# find() 메소드와 착는 방향이 다른 rfind() 메소드
# right와 find를 합친 이름으로 오른쪽부터 찾음
s = 'best of best'
print(s.rfind('best')) # 8

# 4) index()
# find() 메소드와 같은 역할을 수행하며 사용방법도 동일. 두 메소드의 차이점은 문자열이 없을 때 발생
# find() 메소드는 찾는 문자열이 없는 경우 -1을 반환, index() 메소드는 오류 발생
print()
s = 'apple'
print(s.index('p')) # 1
# print(s.index('z')) # ValuesError : substring not found

# 5) 대소문자 변환 메소드
# upper : 모두 대문자로 변환한 결과를 반환
# lower : 모두 소문자로 변환한 결과를 반환
# capitalize : 첫 글자는 대문자로 변환하고 나머지는 소문자로 변환한 결과를 반환
print()
s = 'BEST of best'
print(s.upper()) # BEST OF BEST
print(s.lower()) # best of best
print(s.capitalize()) # Best of best

# 6) join()
# 인수로 전달한 반복가능객체의 각 요소 사이에
# 문자열을 포함시켜 새로운 문자열을 만들고 그 결과를 반환
print()
print('-'.join('python')) # p-y-t-h-o-n

# 7) split()
# 하나의 문자열을 여러 개의 문자열로 분리해서 저장한 리스트를 반환
print()
s = 'Life is too short'
s2 = s.split() # split() 메소드에 아무 인수도 전달하지 않으면 공백문자를 기준으로 각 문자열이 분리
print(s2) # ['Life', 'is', 'too', 'short']

s = '010-1234-5678'
s2 = s.split('-') # 공백대신 특정 문자열을 기준으로 분리하는 방법
print(s2) # ['010', '1234', '5678']

# 8) replace()
# 문자열의 일부 문자열을 다른 문자열로 바꾼 결과를 반환
print()
s = 'Life is too short'
s2 = s.replace('short','long')
print(s2) # Life is too long

# 특정 문자열을 제거하기 위한 용도로 사용
s = '010-1234-5678'
s2 = s.replace('-','')
print(s2) # 01012345678

# 9) 불필요한 문자열 제거 메소드
# 문자열 양끝에 있는 불필요한 문자열을 제거
# strip() : 양쪽 끝에 있는 불필요한 문자열을 제거한 결과를 반환
# lstrip() : 왼쪽 끝에 있는 불필요한 문자열을 제거한 결과를 반환
# rstrip() : 오른쪽 끝에 있는 불필요한 문자열을 제거한 결과를 반환

print()
s = '     apple'
print(len(s)) # 10

s2 = s.lstrip()
print(s2) # apple
print(len(s2)) # 5

# 주민등록번호에서 생년월일 6자리 추출하는 프로그램
# 하이픈 위치가 올바르지 않다면 오류 메시지 출력 후 다시 입력 받도록 처리
while True:
    p = input('하이픈을 포함하여 전체 주민등록번호를 입력하세요 >>> ')
    if p.find('-') != 6: # 문자열 내부에 포함된 특정 문자열을 찾고자 할 때 사용
        print('하이픈의 위치가 잘못되었습니다.')
        continue
        
    birthday = p.split('-')
    print(birthday)
    print(f'생년월일은 {birthday[0]}입니다.')
    print(f'생년월일은 {p[0:6]}입니다.') # 문자열 슬라이싱 사용
    break
    
    # 1. 우리나라의 전화번호는 '지역번호-국번-가입자 개별번호'형식으로 되어 있습니다.
# 어떤 형식의 전화번호를 입력하더라도 '국번'을 추출하여 출력하는 프로그램을 구현하세요.

number = input('전화번호를 입력하세요 >>> ')
hipenIndex = number.find('-')
hipenIndex2 = number.rfind('-')
print(number[hipenIndex+1:hipenIndex2])

# 1-1. find() 메서드와 슬라이싱 활용
phone = input('전화번호를 입력하세요 >>> ')
start = phone.find('-') + 1 # 첫번째 '-'이 나오는 인덱스의 다음 인덱스를 구함
end = phone.find('-',start) # 인덱스를 범위에 지정해 두번째 '-' 인덱스를 구함
code = phone[start:end] # 문자열 슬라이싱을 사용.
print(code)

# 1-2. split() 메소드 활용
phone = input('전화번호를 입력해주세요 >>> ')
code = phone.split('-')[1]
print(code)

#2. '숫자3자리-숫자2자리-숫자5자리' 형식(예: 123-45-67890)의 사업자등록번호를 입력받아서 형식이
# 맞는지 점검하는 프로그램을 구현하세요.
# 다음 지시사항을 모두 점검해야 합니다.

while True:
    saNumber = input('사업자등록번호를 입력하세요(예: 123-45-67890) >>> ')
    if len(saNumber) == 12:
        if saNumber.find('-') == 3 and saNumber.rfind('-') == 6:
            if saNumber.replace('-','').isdecimal() == True:
                print("올바른 형식입니다.")
                break
    else:
        print("올바른 형식이 아닙니다.")
        continue

no = input('사업자등록번호를 입력하세요(예: 123-45-67890) >>> ')
# case 1
if len(no) != 12: # 전체 글자 수 (12) 확인
    print('올바른 형식이 아닙니다.')
elif no.find('-') != 3: # 첫번째 '-' 위치 확인
    print('올바른 형식이 아닙니다.')
elif no.find('-', 4) != 6: #2번째 '-' 위치 확인
    print('올바른 형식이 아닙니다.')
elif not no.replace('-', '').isdecimal(): # '-'을 제외한 문자가 숫자인지 확인
    print('올바른 형식이 아닙니다.')
else:
    print('올바른 형식입니다.')

# case 2
conditon1 = (no.find('-') == 3) # 첫번째 '-' 위치 확인
conditon2 = (no.find('-', 4) == 6) # 두번째 '-' 위치 확인
conditon3 = (len(no) == 12) # 전체 글자 수 (12) 확인
conditon4 = (no.replace('-', '').isdecimal()) # '-'를 제외한 문자가 숫자인지 확인
if conditon1 and conditon2 and conditon3 and conditon4:
    print('올바른 형식입니다.')
else:
    print("올바른 형식이 아닙니다.")

 

2. 리스트 메소드

# 2. 리스트 메소드
# 1) append()
# 리스트의 끝에 인수로 전달된 데이터를 추가

my_list = ['apple', 'banana']
my_list.append('cherry')
print(my_list) # ['apple', 'banana', 'cherry']

# 2) extend()
# 리스트에 다른 리스트나 튜플과 같은 반복가능객체를 추가하여 기존 리스트를 확장
print()
my_list = ['apple', 'banana']
my_list.extend(['cherry', 'mango'])
print(my_list) # ['apple', 'banana', 'cherry', 'mango']

my_list = ['apple', 'banana']
my_list += ['cherry', 'mango']
print(my_list) # ['apple', 'banana', 'cherry', 'mango']

# 3) insert()
# 리스트의 특정 인덱스에 데이터를 추가
print()
my_list = ['apple', 'banana']
my_list.insert(0, 'cherry')
print(my_list)

# 4) clear()
# 리스트에 저장된 모든 요소를 삭제
print()
my_list = ['apple', 'banana']
my_list.clear()
print(my_list) # []

my_list = ['apple', 'banana']
my_list = []
print(my_list) # []

# 5) pop()
# 리스트이 마지막 요소가 반환되면서 삭제
print()
my_list = ['apple', 'banana']
item = my_list.pop()
print(item) # banana
print(my_list) # ['apple']

# 인덱스 값을 인수로 전달하면 해당 인덱스 값이 삭제
my_list = ['apple', 'banana']
item = my_list.pop()
print(item) # apple
print(my_list) # ['banana']

# 6) remove()
# 인수로 전달된 값과 동일한 요소를 찾아서 제거. 동일한 요소가 여러 개인 경우에는 첫 번째 요소가 제거
print()
my_list = ['apple', 'banana']
my_list.remove('cherry')
print(my_list) # ['apple', 'banana', 'mango']

# 중복된 값이 있는 경우 제일 앞에 있는 것만 삭제
my_list = ['apple', 'banana', 'cherry', 'mango', 'cherry']
my_list.remove('cherry')
print(my_list) # ['apple', 'banana', 'mango', 'cherry']

# 특정 값을 전부 삭제를 원할 경우 반복문 사용
my_list = ['apple', 'banana', 'cherry', 'mango', 'cherry']
for idx in range(my_list.count('cherry')):
    my_list.remove('cherry')
print(my_list)

 

3. 사용자 정의 함수

 - 함수 용어 정리
 - 1. 함수 정의 : 사용자 함수를 새로 만드는 것을 의미
 - 2. 인수 : 사용자 함수에 전달할 입력(input)을 의미. argument
 - 3. 매개변수 : 인수를 받아서 저장하는 변수를 의미. parameter
 - 4. 반환값 : 사용자 함수의 출력(output)을 의미. return
 - 5. 함수 호출 : 만들어진 사용자 함수를 실제로 사용하는 것을 의미

# 함수 정의
# 함수를 만드는 것을 의미. def 키워드를 이용

# def 함수이름(매개변수) :
#   본문
#   return 반환값
# 함수이름을 개발자가 마음대로 결정
# 매개변수, 반환값을 필수 사항이 아님

# 함수 호출
# 변수 = 함수이름(인수)
# 함수의 호출 결과를 저장할 변수를 생략가능

# 4가지 함수 호출 형태
# 1) 인수 : X, 반환값 : X
# 함수이름()
# 2) 인수 : O, 반환값 : X
# 함수이름(인수)
# 3) 인수 : X, 반환값 : O
# 변수 = 함수이름()
# 4) 인수 : O, 반환값 : O
# 변수 = 함수이름(인수)

 

# 사용자 정의 함수
# 사용자가 직접 만든 함수
# 1) 어떤 입력을 받아 2) 특정 연산을 수행한 뒤 3) 결과를 반환하는 기능

# 함수 용어 정리
# 1. 함수 정의 : 사용자 함수를 새로 만드는 것을 의미
# 2. 인수 : 사용자 함수에 전달할 입력(input)을 의미. argument
# 3. 매개변수 : 인수를 받아서 저장하는 변수를 의미. parameter
# 4. 반환값 : 사용자 함수의 출력(output)을 의미. return
# 5. 함수 호출 : 만들어진 사용자 함수를 실제로 사용하는 것을 의미


# 함수 정의
# 함수를 만드는 것을 의미. def 키워드를 이용

# def 함수이름(매개변수) :
#   본문
#   return 반환값
# 함수이름을 개발자가 마음대로 결정
# 매개변수, 반환값을 필수 사항이 아님

# 함수 호출
# 변수 = 함수이름(인수)
# 함수의 호출 결과를 저장할 변수를 생략가능

# 4가지 함수 호출 형태
# 1) 인수 : X, 반환값 : X
# 함수이름()
# 2) 인수 : O, 반환값 : X
# 함수이름(인수)
# 3) 인수 : X, 반환값 : O
# 변수 = 함수이름()
# 4) 인수 : O, 반환값 : O
# 변수 = 함수이름(인수)

# welcome() 함수 정의
def welcome():
    print('Hello Python')
    print("Nice to meet you")

welcome() # 함수를 정의한 후에 호출 해야 함

# 파이썬 함수의 단점 : 데이터 타입이 없어서 다른 작업자가 만든 함수를 사용할 때 주의할 점이 많음
def process(number):
    return number / 1

process("helloo") # TypeError: unsupported operand type(s) for /: 'str' and 'int'

# 어노테이션 사용 가능. 타입 강제는 아님
def process(number: int) -> float:
    return number / 1

# 인수와 매개변수
# 함수로 전달되는 인수(argument)를 저장하는 변수를 매개변수(parameter)라고 함

# 1. 인수가 있는 함수
def introduce(name, age):
    print(f'내 이름은 {name}이고, 나이는 {age}살 입니다.')

introduce('james', 25) # 내 이름은 james이고, 나이는 25살 입니다.
introduce(age=25, name='james') # 내 이름은 james이고, 나이는 25살 입니다.

# 2. 가변 매개변수
# 함수로 전달해야 하는 인수의 개수가 정해지지 않아도 매개변수를 선언할 수 있음
# 가변 매개변수를 만드는 키워드는 애스터리스크(*)
# 매개변수 앞에 *를 붙이면 곧바로 가변 매개 변수가 되면서 전달되는 모든 인수를 하나의 튜플(tuple)로 만들어 줌

def show(*args):
    for item in args:
        print(item)
        
show('python') # show 함수 호출. 인수가 1개
show('happy','birthday') # show 함수 호출. 인수가 2개

# 3. 디폴트 매개변수
# 매개변수로 전달되는 인수가 없는 경우에 기본적으로 사용할 수 있도록
# 매개변수에 기본값을 설정할 수 있음

print()
def greet(message='안녕하세요'):
    print(message)

greet('반갑습니다.') # 반갑습니다
greet() # 안녕하세요

# 디폴트 매개변수와 일반 매개변수를 같이 사용하는 경우 디폴트 매개변수를 뒤(오른쪽)으로 배치
def greet(name, message="안녕하세요"):
    print(f'{name}님 {message}.')

greet('김철수') # 김철수님 안녕하세요
greet('김철수', '반갑습니다.') # 김철수님 반갑습니다.

greet() # 이철수님 안녕하세요
greet('김철수') # 김철수님 안녕하세요. 왼쪽 부터 적용.
greet('김철수', '반갑습니다') # 김철수님 반갑습니다.

# 반환값
# 함수 호출 결과를 반환값(return value)
# 반환값이 있으면 함수 내부에서 return 문을 통해 값을 반환할 수 있고,
# 반환값이 없으면 함수 내부에 return문을 작성할 필요가 없음

def address():
    string = "우편번호 12345\n"
    string += '서울시 영등포구 여의도동'
    return string

print(address()) # None : 반환값이 없어서 출력이 안됨

# 2. 다중 반환
# 하나의 반환값도 처리할 수 있고 여러 개의 반환값도 처리할 수 있음

print()
def calculator(*args):
    return sum(args), sum(args) / len(args), max(args), min(args)

a, b, c, d = calculator(1, 2, 3, 4, 5) # 4개의 반환값을 모두 저장하기 위해서 변수 4개 배치
print('합계', a) # 합계 15
print('평균', b) # 평균 3.0
print('최댓값', c) # 최댓값 5
print('최솟값', d) # 최솟값 1

print() # result는 4개의 반환값을 저장하는 튜플
result = calculator(1, 2, 3, 4, 5)
print('합계', result[0])
print('평균', result[1])
print('최댓값', result[2])
print('최솟값', result[3])

# 다중 반환 일 때, 변수 갯수에 맞게 또는 한개로 지정해야 함

# 3. 함수의 종료를 위한 return
# 반환값이 있으면 return문을 사용해 반환하고, 반환값이 없으면 return문을 생략하면 됨
# 반환값이 없을 때도 return문을 작성하는 경우 -> 함수를 종료할 때
print()

def charge(energy):
    if energy < 0:
        print('0보다 작은 에너지는 충전할 수 없습니다.')
        return # charge() 함수의 종료를 의미
    print('에너지가 충전되었습니다.')

charge(1) # 에너지가 충전되었습니다.
charge(-1) # 0보다 작은 에너지는 충전할 수 없습니다.

# 4. 파이썬의 함수는 객체이고 자료형이다.
print(charge) # <function charge at 0x000001EA42448DC0>

def print_charge(fun):
    fun(0) # 에너지가 충전되었습니다.
    
print_charge(charge) # 함수를 함수 호출시 인수로 사용이 가능

# 5. 함수안에 함수 선언도 가능하다.
def print_greet(name):
    def get_greet():
        return '안녕하세요'
    
    print(name + "님" + get_greet())
    
print_greet('김철수')

 

4. 지역변수와 전역변수

# 지역변수와 전역변수
# 1. 지역변수 local variable
# 함수 내부에서 선언한 변수는 함수 내부에서만 사용. 함수 외부에서는 지역변수에 접근할 수 없음

def f():
    a = 10
    print(f'f() 내부 : {a}')

f() # f() 내부 : 10
# print(f'f() 외부: {a}') # 함수 외부에서는 a 변수를 사용할 수 없음

# 2. 전역변수 global vairable
# 함수 외부에서 선언한 변수는 함수 내부나 함수 외부에서 모두 사용할 수 없음
print()

def f():
    print(f'f() 내부 : {b}')

b = 10 # 전역변수
f() # f() 내부 10
print(f'f() 외부 : {b}') # f() 내부 10

# 1) 전역변수를 단순히 참조만 하는 경우 -> 읽기만 하는 경우
print()
a = 0
def f():
    print(a) # 함수 f() 내부에서 전역변수 a를 참조

f() # 0
print(a) # 0 / 함수 f() 외부에서 전역변수 a를 참조

# 2) 전역변수의 값을 변경하는 경우 : 파이썬의 경우 변수 초기화와 변수 값 수정이 문법적으로 똑같음
print()
a = 0

def f():
    global a # 전역변수 a를 사용할 때, global을 붙혀 준다
    a = 10 # 전역변수 a의 값을 변경

f() # 함수 f() 실행
print(a) # 10 / 전역변수의 변경된 값을 확인

# 커피 자판기 프로그램
def coffee_machine(money: int, pick: str):
    print(f'{money}원에 {pick}를 선택하셨습니다.')
    # 커피와 가격을 하나의 데이터로 처리하기 위해 딕셔너리 dict를 사용
    menu = {
        '아메리카노' : 1000,
        '카페라떼' : 1500,
        '카푸치노' : 2000
    }

    if pick not in menu: # 없는 커피를 주문하는 경우
        print(f'{pick}는 판매하지 않습니다.')
        return money, '없는 메뉴'
    elif menu[pick] > money: # 구매할 금액이 부족한 경우
        print(f'{pick}는 {menu[pick]}원 입니다.')
        return money, '금액 부족'
    else: # 정상 주문이면 잔돈과 선택한 커피를 반환
        return money - menu[pick], pick


order = input('커피를 선택하세요. (아메리카노, 카페라떼, 카푸치노) >>> ')
pay = int(input('얼마를 내시나요? >>> '))
coffee_machine(pay, order)


# 1. 700원짜리 음료수를 뽑을 수 있는 자판기 프로그램을 구현하세요.
# 돈을 넣으면 몇 잔의 음료수를 뽑을 수 있는지 그리고 잔돈은 얼마인지 모든 경우의 수를 출력하도록 구현하세요.

def vending_machine(money):
    for idx in range(0, (money//700)+1):
        print(f'음료수 = {idx}개, 잔돈 = {money - 700*idx}원')
vending_machine(3000)

def get_average(marks: dict):
    return sum(marks.values()) / len(marks)

marks = {'국어':90, '영어':80, '수학':85}
average = get_average(marks)
print(f'평균은 {average}입니다.')

 

5. 모듈 module 

- converter.py

# MILES, POUND는 단위 변환에서 사용하는 변수
MILES = 0.621371
POUND = 0.00220462

def kilometer_to_miles(kilometer: int | float): # 킬로미터를 마일로 변환
    """ 킬로미터를 마일로 변환 """
    return kilometer * MILES

def grams_to_pounds(gram: int | float) -> float: # 그램을 파운드로 변환하는 함수
    """ 그램을 파운드로 변환하는 함수 """
    return gram * POUND

 

 -  모듈.py

# 1. 모듈이란
# 모듈 module 이란 한 마디로 파이썬 파일(.py)
# 언제든지 사용할 수 있도록 변수나 함수 또는 클래스를 모아 놓은 파일

# 2. 모듈생성
# converter.py 생성

# 3. 모듈의 사용
# 반드시 같은 디렉토리에 있어야 함
# 모듈에 저장된 함수를 사용하는 방법
# 1. 모듈 전체를 가져오는 방법
# 모듈에 저장된 '모든' 클래스나 함수를 사용하고자 할 때
# 예) import 모듈

import converter

miles = converter.kilometer_to_miles(150) # 모듈.함수() 형식으로 호출
print(f'150km={miles}miles') # 150km = 93.20565miles

pounds = converter.grams_to_pounds(1000)
print(f'1000g={pounds}pounds') # 1000g = 2.20462pounds

# 2. 모듈에 포함된 함수 중에서 특정 함수만 골라서 가져오는 방법
# 예) from 모듈 import 함수
# 예) from 모듈 import 함수1, 함수2
# 예) from 모듈 import *

print()
from converter import kilometer_to_miles # 모듈은 가져오지 않고 특정 함수만 가져옴

miles = kilometer_to_miles(150) # 모듈명을 명시하지 않고 사용
print(f'150km={miles}miles') # 150km=93.20565miles

print()
from converter import * # 모듈은 가져오지 않고 모듈의 모든 함수 가져옴

miles = kilometer_to_miles(150) # 모듈명을 명시하지 않고 사용
print(f'150km={miles}miles')

pounds = grams_to_pounds(1000) # 모듈명을 명시하지 않고 사용
print(f'1000g={pounds}pounds')

# 4. 별명 사용하기
# 모듈이나 함수를 import 하는 경우에 원래 이름 대신 별명 alias를 지정하고 사용
# 모듈이나 함수의 이름이 긴 경우에 주로 짧은 별명을 지정하고 긴 본래 이름 대신 사용
# 별명을 지정할 때는 as 키워드를 사용
print()
import converter as cvt # converter 모듈에 cvt라는 별명을 지정

miles = cvt.kilometer_to_miles(150) # 별명을 이용해서 함수 사용
print(f'150km={miles}miles')

pounds = cvt.grams_to_pounds(1000)
print(f'1000g={pounds}pounds')

print()
from converter import kilometer_to_miles as k_to_m # 함수에도 별명 지정 가능

miles = k_to_m(150) # 함수 이름 대신 별명을 사용
print(f'150km={miles}miles')

 

6. 내부모듈

 - 파이썬 기본 저장된 모듈

# 1. math (수학관련 모듈)

import math # import 후 사용
# 1) 원주율 pi
# 더 정확한 파이 값을 사용하기 위해
print(math.pi)  # 3.141592653589793

# 2) ceil() 함수와 floor() 함수
# 전달된 값을 정수로 올림 처리하거나 내림 처리
print(math.ceil(1.1))  # 2 / 정수로 올림 처리
print(math.floor(1.9))  # 1 / 정수로 내림 처리

# 3) trunc() 함수
# 전달된 값을 정수로 절사
# 양수를 처리할 때는 차이가 없지만, 음수를 처리할 때는 결과의 차이가 있슴
print(math.trunc(-1.9))  # -1 / 절사이므로 소수점 이하를 잘라버림
print(math.floor(-1.9))  # -2 / 내림이므로 -1.9 보다 작은 정수로 내림

# 4) sqrt() 함수
# 제곱근 구함
print()
print(math.sqrt(25))  # 5.0 / 루트 25를 의미

# 5) pow() 함수
# 제곱을 구함
print()
print(math.pow(2, 3))  # 8.0 / 2의 3제곱을 의미

# 2. random 모듈
# 난수 random number를 생성하는 모듈
# 난수를 통해서 간단한 게임을 제작할 수 있고 확률 처리도 할 수 있음

import random

# 1) randint() 함수
# 전달하는 두 인수 사이의 정수를 임의로 생성
print()
print(random.randint(1,10)) # 랜덤 정수 1개 / 1 이상 10 이하의 정수

# 2) randrange() 함수
# range() 함수와 사용 방법이 비슷
# range() 함수는 특정범위의 정숫값들을 모두 생성할 수 있지만, 
# randrange() 함수는 그 특정 범위에 속한 정수 중 하나만 임의로 생성
print()
print(random.randrange(10)) # 0이상 10 미만의 정수
print(random.randrange(1, 10)) # 1이상 10미만의 정수
print(random.randrange(1,10,2)) # 1이상 10미만의 홀수

# 3) random() 함수
# 0이상 1미만 범위에서 임의의 실수를 생성
# 0이상 1미만 범위를 백분율로 환산하면 0%이상 100%미만이기 때문에 확률을 처리할 때도 사용
print()
print(random.random()) # 0.224245

# 50% 확률로 '안녕하세요' 출력
if random.random() < 0.5:
    print('안녕하세요')

rand = random.randint(1, 2)
print(rand)
if rand == 1:
    print('안녕하세요')

# 4) choice() 함수
# 전달된 시퀀스 자료형에 속한 요소 중에서 하나를 임의로 반환
print()
seasons = ['spring', 'summer', 'fall', 'winter']
print(random.choice(seasons)) # 랜덤 하나

idx = random.randint(0, len(seasons) - 1)
print(seasons[idx])

# 5) sample() 함수
# 전달된 시퀀스 자료형에 속한 요소 중 지정된 개수의 요소를 임의로 반환
# 반환 결과는 리스트 list 자료형이며 중복없이 임의의 요소가 선택

print()
print(random.sample(range(1, 46), 6)) # 6개 임의로 추출해서 리스트로 반환

seasons = ['spring', 'summer', 'fall', 'winter']
print(random.sample(seasons, 3))
seasons = ['summer', 'summer', 'summer', 'winter']
print(random.sample(seasons, 3))

# 6) shuffle() 함수
# 전달된 시퀀스 자료형에 속한 요소의 순서를 임의로 조정하여 다시 재배치하는 함수
# 호출하면 실제 전달된 시퀀스 자료형의 순서가 재배치
print()
my_list = [1, 2, 3, 4, 5]
random.shuffle(my_list)
print(my_list)



# 3. time 모듈
import time

# 1) time() 함수
# 1970년 1월 1일 0시 0분 0초 부터 현재까지 경과된 시간 timestamp을 반환
# 소수점 이하는 마이크로 초를 의미
print(time.time())  # 1645240996.2733545

# 2) ctime() 함수
# 인수로 전달된 시간 timestamp을 형식에 갖춰 반환
print(time.ctime(time.time()))  # Sat Feb 19 12:23:16 2022

# 3) strftime() 함수
# 인수로 전달된 날자와 지시자를 이용하여 형식을 갖춘 날짜 데이터가 문자열로 반환
# 년 : %y : 2자리 날짜로 표시
# 년 : %Y : 4자리 날짜로 표시
# 월 : %m : 2자리 숫자로 표시 (01 ~ 12)
# 월 : %b : 3자리 영문으로 표시 (Jan ~ Dec)
# 월 : %B : 전체 영문으로 표시 (January ~ December)
# 일 : %d : 2자리 숫자로 표시 (01 ~ 31)
# 요일 : %a : 3자리 영문으로 표시 (Sun ~ Sat)
# 요일 : %A : 전체 영문으로 표시 (Sunday ~ Saturdy)
# 시 : %l : 12시간제로 표시 (01 ~ 12)
# 시 : %H : 24시간제로 표시 (00 ~ 23)
# 분 : %M : 2시간제로 표시 (00 ~ 59)
# 초 : %S : 2시간제로 표시 (00 ~ 59)
# 오전 / 오후 : %p : AM 또는 PM
print(time.strftime('%Y-%m-%d %H:%M:%S'))

# 4) sleep() 함수
# 인수로 전달된 초 second 만큼 시스템을 일시 정지
time.sleep(1)

# 4. datetime 모듈
# 날짜와 시간 데이터를 처리할 때 사용
print()
import datetime

# 1) now() 메소드
# datetime 클래스 내부에 정의된 메소드
# 시스템의 현재 날짜와 시간을 반환
present = datetime.datetime.now()
print(present)

# 2) date() 함수
# 특정날짜를 반환
birthday = datetime.date(2014, 8, 25)
print(birthday)  # 2014-08-25

# 3) time() 함수
# 특정시간을 반환
wake = datetime.time(10, 48, 0)
print(wake)  # 10:48:00

# 4) 날짜 / 시간 관련 필드값
# 특정 날짜에 원하는 데이터만 추출하고자 할때 이용
today = datetime.datetime.now()
print(today.year)  # 년도
print(today.month)  # 월
print(today.day)  # 일
print(today.hour)  # 시
print(today.minute)  # 분
print(today.second)  # 초

# 5) timedelta() 함수
# 날짜 / 시간 데이터의 연산을 위하여 사용
# 1주 : timedelta(weeks=1)
# 1일 : timedelta(days=1)
# 1시간 : timedelta(hours=1)
# 1분 : timedelta(minutes=1)
# 1초 : timedelta(seconds=1)

today = datetime.datetime.now()
yesterday = today - datetime.timedelta(days=1)  # 어제 구함
tomorrow = today + datetime.timedelta(days=1)  # 내일 구함
print(yesterday)
print(tomorrow)

# 6) total_seconds() 메소드
# 어떤 기간에 포함된 총 시간의 초 seconds 로 반환
date1 = datetime.date(2020, 8, 25)
date2 = datetime.date(2020, 8, 26)
print(date2 - date1)  # 1 day, 0:00:00
print((date2 - date1).total_seconds())  # 86400.0 = 60초 * 60분 * 24시간

 

7. 외부모듈

# 외부 모듈의 이용
# 1. 패키지
# 모듈의 상위 개념. 모듈의 집합을 의미
# 파이썬에서 기본적으로 제공하지 않더라도 외부에서 만들어진 패키지를 이용하면
# 패키지에 포함된 모듈을 사용할 수 있음

# 2. 패키지 관리자
# 외부 모듈을 사용하기 위해서는 우선 모듈이 포함된 패키지를 추가로 설치
# pip라고 불리는 패키지 관리자를 사용해서 패키지를 추가나 삭제

# 3. 패키지 설치
# 1) 터미널 창에
# pip install packge

# 2)
# 메뉴 File > Setting > Python Interpreter > +
# > numpy 검색 > 설치

# numpy 패키지는 수치해석과 통계에서 많이 사용
# pip install numpy

import numpy as np
print(np.sum([1,2,3,4,5])) # 15

# 4. 패키지 삭제
# pip uninstall package
# 예) pip uninstall numpy

 

8. 모듈 연습문제

import time, random, math
from datetime import datetime

""" 
1. 자동으로 실행되는 로또 추첨 프로그램을 다음 지시사항에 따라 구현하세요.

지시사항
1. 1에서 45 사이의 모든 정수를 순서대로 pot 리스트에 저장합니다.
2. 다음 과정을 6번 반복합니다.
 * pot 리스트를 무작위로 섞어줍니다.
 * pot 리스트의 마지막 숫자를 하나만 빼서 jackpot 리스트에 저장합니다.
 * 2초 동안 잠시 멈춥니다.
3. jackpot 리스트의 모든 요소를 오름차순 정렬합니다.
4. jackpot 리스트의 모든 요소를 출력합니다. 
"""
jackpot = []
for i in range(6):
    pot = random.randint(1,45)
    time.sleep(0.5)
    print(f'{i+1}번째 당첨번호는 {pot}입니다.')
    jackpot.append(pot)
jackpot = sorted(jackpot)
print(jackpot)

pot = list(range(1,46)) # 1에서 45 사이의 모든 정수를 순서대로 pot 리스트에 저장
jackpot = list()
for n in range(6): # 6번 반복
    random.shuffle(pot) # pot 리스트에 무작위로 섞어줌
    # pot 리스트의 마지막 숫자를 하나만 빼서 jackpot 리스트에 저장
    jackpot_num = pot.pop()
    jackpot.append(jackpot_num)
    time.sleep(2)
    print(f'{n+1}번째 당첨번호는 {jackpot_num} 입니다.')

jackpot.sort() # jackpot 리스트의 모든 요소를 오름차순 정렬
print(f'이번 당첨번호는 {jackpot} 입니다.')

"""
2. 다음 지시사항에 따라 UpDown게임을 구현하세요.

지시사항
1. 1에서 100 사이의 정수 중 하나를 임의로 생성하면
사용자는 그 숫자를 맞힐 때까지 값을 예상하여 입력합니다.
2. 사용자가 입력한 값이 정답보다 작으면 Up, 정답보다 크면 Down을 출력합니다.
3. 정답을 맞히면 몇 초 만에 정답을 맞혔는지 출력하세요.
이때 소수 아래 값은 내림 처리하여 정수로 출력하세요."""

number = random.randint(1,100)
time1 = datetime.now()
while True:
    print("UpDown게임을 시작합니다.")
    numberAns = int(input("어떤 값일까요? >>>"))
    if numberAns > number:
        print("Down")
        continue
    elif number > numberAns:
        print("UP")
        continue
    elif numberAns == number:
        print(f'{numberAns}! 정답입니다.')
        print(f'{math.floor((datetime.now() - time1).total_seconds())}초 만에 성공했습니다.')
        break


num = random.randint(1, 100) # 1에서 100 사이의 정수 중 하나를 임의로 생성
print('UpDown게임을 시작합니다.')
start = time.time() # 시작시간
while True:
    answer = int(input('어떤 값일까요? >>> '))
    if answer == num: # 정답을 맞춘 경우
        print(f'{num}! 정답입니다.')
        break

    if answer > num:
        print(f'Down')
    else:
        print(f'Up')
end = time.time() # 종료시간
print(f'{math.floor(end-start)}초 만에 성공했습니다.')