[Week1] Day2 파이썬 기초 문법

이규호·2021년 1월 19일
0

부스트캠프 U Stage

목록 보기
2/30

📒 Variables


파이썬의 기초 변수와 리스트들에 대한 강의였다.
이미 다 아는 내용이였지만, 복습은 언제나 옳다.

📝 variable & memory


✏️ 변수(variable)

가장 기초적인 프로그래밍 문법 개념이다.
데이터(값)을 저장하기 위한 메모리 공간의 프로그래밍상 이름이다.

a = 1  #a라는 "변수"에 1이라는 "값"을 넣어라!

변수는 메모리 주소를 가지고 있고, 값은 메모리 주소에 할당된다.
변수가 선언 되는 순간 메모리 특정영역에 물리적인 공간이 할당된다.

✏️ 폰 노이만 아키텍쳐

모든 값은 메모리 어딘가에 저장이 된다.
사용자가 컴퓨터에 값을 입력하는 경우 메모리에 저장된 값을 CPU로 불러와 처리한다.
메모리 주소의 이름을 직접 쓰긴 어렵기 때문에, 변수로 접근할 수 있게 하는 것이다.
CPU : 제어 장치 + 산술논리 장치

✏️ Variable Identifier

  • 일반적으로 기억할 수 있는, 의미 있는 이름을 사용한다.
  • 줄임말을 쓰지 않는 것을 권장한다.
  • 대소문자를 구분하며 알파벳, 숫자, '_'로 선언 가능하다.
  • 특별한 의미가 있는 예약어는 쓰지 않는다. ex) if, for 등

📝 Basic Operator


✏️ Data type

코드를 실행하는 시점에 데이터의 Type이 결정된다.
float(), int() 등을 사용하여 데이터의 형변환이 가능하다. (내림 처리)
다양한 Data Type이 하나의 List에 들어간다. (List 안에 List도 입력 가능하다.)

✏️ Operation

'+', '-', '*', '/' 와 같은 기호들을 연산자(operand)라고 칭한다.
연산자에 의헤 계산이 되는 숫자들은 피연산자(operand)라고 칭한다.
연산의 순서는 실제 수학에서의 연산 순서와 같다.

a + b # a, b는 피연산자. +은 연산자
a ** 3 # a의 3승(거듭 제곱)
a % 3 # a를 3으로 나누었을 때, 나머지
a // 3 # a를 3으로 나누었을 때, 몫
(a = a + 1) == (a += 1)

📝 List or Array


시퀸스 자료형으로, 여러 데이터들의 집합을 의미한다.
int, float와 같은 다양한 데이터 타입을 포함하고 있다.

✏️ 인덱싱(Indexing)

list에 있는 값들은 주소(offset)를 가진다.
주소를 사용해 할당된 값을 호출하는 방식을 인덱싱이라고 한다.
>>> colors = ["red", "blue", "green", "yellow", "black", "white"]
>>> colors[0]
red  # 주소값으로 접근했다.

✏️ 슬라이싱(Slicing)

list의 값들을 잘라서 쓰는 것을 의미한다.
list의 주소 값을 기반으로 부분 값을 반환해준다.
>>> colors[1:4] # 범위를 초과하면 자동으로 최대 범위를 지정해준다.
['blue', 'green', 'yellow'] # 1번째 인덱스부터 (4-1)번째 인덱스까지
>>> colors[:]
['red', 'blue', 'green', 'yellow', 'black', 'white'] # 전체 범위
>>> colors[3:]
['yellow', 'black', 'white'] # 3번째 인덱스부터 끝까지
>>> colors[::2]
['red', 'green', 'black'] # 인덱스를 2칸씩 증가시킨다.

✏️ 리스트의 연산

>>> color = ['red, blue', 'green']
>>> color2 = ['yellow', 'black', 'white']
>>> len(color)
3 # list의 길이
>>> print(color + color2)
['red', 'blue', 'green', 'yellow', 'black', 'white'] # 리스트 합치기
>>> print(color * 2)
['red', 'blue', 'green', 'red', 'blue', 'green'] # 리스트 반복
>>> 'blue' in color
True # 내부에 해당 값이 있는지 여부 반환
>>> color.append('yellow') # 리스트 뒤에 변수 추가
>>> color.extend(['black','white']) # 리스트 뒤에 새로운 리스트 추가
>>> color.insert(0, 'orange') 0번째 주소에 변수 추가
>>> print(color)
['orange', 'red', 'blue', 'green', 'yellow', 'black', 'white']
>>> color.remove('white') 리스트에서 변수 삭제
>>> del color[0] 0번째 주소 리스트 객체 삭제
>>> print(color)
['red', 'blue', 'green', 'yellow', 'black']

⭐️ 리스트 메모리 저장 방식

a = list(), b = list()
a = b # a에 b 리스트의 주소를 할당한다. 서로 같은 곳을 가르킨다.
a = b[:] # a에 b의 값만 복사한다. 서로 다른 곳을 가르킨다.

import copy
a_copy = copy.deepcopy(a) # 2차원 이상일 때 유용

✏️ 패킹, 언패킹

>>> l = [1, 2]
>>> a, b = l
>>> print(a, b)
1 2
>>> a, b = b, a # 간단히 swap 가능하다!
>>> print(a, b)
2 1

📒 Function and Console I/O


새삼 느끼지만 교수님이 설명을 너무 잘하시는 것 같다..
다 아는 내용이였지만 말씀하시는 내용이 이해가 너무 잘 됐다.

📝 Function


반복적인 수행을 단 1회만 작성후 호출할 수 있다.
코드를 논리적인 단위로 분리하여, 가독성이 높아진다.
캡슐화 : 인터페이스만 알면 타인의 코드를 쉽게 사용할 수 있다.

# 함수의 기본 문법
def fucntion_name(parameter1, parameter2) :
	#수행문 1 (tap 필수 !)
	#수행문 2
	return return_value #생략 가능(void function에서)

✏️ 함수의 종류

parameter : 함수의 입력 값 인터페이스
argument : 실제 parameter에 대입된 값
parameter 유무, 반환 값 유무에 따라 함수의 형태가 다르다.

parameter 없음parameter 존재
반환 값 없음함수 내의
수행문만 수행
parameter를 사용,
수행문만 수행
반환 값 존재parameter 없이, 수행문
수행 후 결과 값 반환
parameter를 사용하여
수행문 수행 후 결과값 반환
# 예시
def f(x):
	print(x + 10)
    
def g(x):
	return x + 10

>>> c = f(20)
30
>>> print(c)
None # 반환 값이 없다.
>>> c = g(20)
>>> print(c)
30 # 반환 값이 있어서, 할당이 되었다.

📝 Console I/O


✏️ input() 함수는 콘솔창에서 문자열을 입력 받는 함수이다.

name = input() # 콘솔창에서 입력한 값을 name에 저장
age = int(input()) # 입력 시 바로 형 변환을 할 수 있다.

✏️ 입출력 기법

>>> print("hello", "world!", 100)
hello world! 100 # print 시 ','를 넣으면 print문이 공백으로 연결된다.
>>> name = input("나이를 입력하세요 : ")
나이를 입력하세요 :  # 입력을 받기 전에 출력을 할 수 있다.

✏️ print formatting

>>> print(1, 2, 3)
1 2 3 
>>> print("a" + " " + "b" + " " + "c")
a b c
>>> print("%d %d %d" % (1, 2, 3))
1 2 3
>>> print("{} {} {}".format("a", "b", "c"))
a b c
>>> value = 100
>>> print(f"value is {value}"
value is 100

✏️ % format type

typeDesc.
%s문자열(String)
%c문자 1개(character)
%d정수(Integer)
%f부동소수(floating-point)
%o8진수
%x16진수
%%Literal % (문자 % 자체)

✏️ padding & naming

>>> name = Gyuho
>>> age = 26
>>> print(f"Hello, {name}, You are {age}.")
Hello, Gyuho, You are 26.
>>> print(f'{name:10}')
Gyuho
>>> print(f'{name:>10}')
     Gyuho
>>> print(f'{name:*<10}')
Gyuho*****
>>> print(f'{name:*>10}')
*****Gyuho
>>> print(f'{name:*^10}')
**Gyuho***
>>> pi = 3.14159265
>>> print(f'{pi:.2f}')
3.14

📒 Conditionals and Loops


하루만에 Python의 대부분 문법을 익혔다.
AI 강좌에 앞서서 이런 시간을 가진 것이 뜻 깊게 느껴졌다.

👉 프로그램 작성 시, 조건에 따른 판단반복필수이다.

📝 조건문


조건에 따라 특정한 동작을 하게하는 명령어

생활에서의 프로그램 예시

  • 지하철 앞 차 간격이 10M 이하속도를 10km 이하로 늦춰라
  • 사용자가 20세 이하VOD를 플레이 하지 마라
  • 휴대폰 패턴이 5회 틀리면 20초 동안 대기 상태로 만들어라

조건문은 조건을 나타내는 기준실행해야 할 명령으로 구성된다.
조건의 참, 거짓에 다라 실행해야 할 명령이 수행되거나 되지 않는다.

파이썬은 조건문으로 if, else, elif 등의 예약어를 사용한다.

# if - elif - else 문 기본 문법
if <조건> :
    <수행 명령 1-1>
    <수행 명령 1-2>
elif <조건2> :
    <수행 명령 2-1>
    <수행 명령 2-2>
else :
    <수행 명령 3-1>
    <수행 명령 3-2>

📝 조건 판단 방법

비교연산자비교상태설명
x < y~보다 작음x가 y보다 작은지 검사
x > y~보다 큼x가 y보다 큰지 검사
x == y값이 같음x와 y의 값이 같은지 검사
x is y주소가 같음x와 y의 메모리 주소가 같은지 검사
x != y값이 같지 않음x와 y의 값이 다른지 검사
x is not y주소가 같지 않음x와 y의 메모리 주소가 다른지 검사
x >= y크거나 같음x가 y 이상인지 검사
x <= y작거나 같음x가 y 이하인지 검사
a and band 연산자a와 b 모두 참인지 검사
a or bor 연산자a 또는 b가 참인지 검사
all(list)and listlist 내부 모든 원소들에 대해 and 연산
any(list)or listlist 내부 모든 원소들에 대해 or 연산
# 삼항 연산자 예시
is_even = True if value % 2 == 0 else False
# 조건이 참이면 True, 아니면 Fals 반환

📝 반복문


정해진 동작을 반복적으로 수행하게 하는 명령어

생활에서의 프로그램 예시

  • 100명의 학생의 성적을 산출할 때
  • 검색 결과를 출력해 줄 때
  • 워드에서 단어 바꾸기 명령 실행

반복문은 반복 시작 조건, 종료 조건, 수행 명령으로 구성된다.
반복 구문은 들여쓰기block으로 구분된다.

파이썬에서는 반복문으로 for, while 등의 예약어를 사용한다.

✏️ for문

# for 문 기본 문법
>>> for i in [1, 2, 3, 4, 5] :
... 	print(i)
...
1 2 3 4 5 # (사이는 원래 endl)

>>> for i in range(0, 5) : # 0부터 (5-1)까지
... #for i in range(5) 와 같은 문법이다.(시작 디폴트가 0)
... 	print(i)
...
0 1 2 3 4 # (사이는 원래 endl)

>>> for i in range(1, 10, 2) : # 2칸씩 증가
... 	print(i)
...
1 3 5 7 9 # (사이는 원래 endl)

>>> for i in range(10, 1, -1) : # 내림차로도 가능
... 	print(i)
...
10 9 8 7 6 5 4 3 2 # (사이는 원래 endl)

>>> for i in "abcdefg" :
... 	print(i)
...
a b c d e f g # (사이는 원래 endl)

>>> for i in ["ab", "cd", "ef"] :
... 	print(i)
...
ab cd ef # (사이는 원래 endl)

✏️ while문

조건이 만족하는 동안 반복 명령문을 수행하는 예약어이다.

# while 문 기본 문법
>>> i = 1
>>> while i < 10 : # i가 10 미만일 때만 수행
... 	print(i)
... 	i += 1 # 탈출할 수 있는 구문이 필요
...
1 2 3 4 5 6 7 8 9 # (사이는 원래 endl)

일반적으로 반복 실행 횟수를 명확히 알 때는 for 문을 사용하고,
반대로 반복 실행 횟수가 명확하지 않을 때는 while 문을 사용한다.

✏️ 기타 예약어

  • break : loop를 바로 탈출하는 예약어.
  • continue : 아래 수행문을 생략하고 다음 반복 구문으로 넘어가는 예약어.

📝 Debugging


        "실수하지 않는 사람은 없다!"

에러를 핸들링 하는 것은 코딩에서 굉장히 중요하다.
코드의 오류를 발견하여 수정하는 과정을 디버깅이라고 한다.

오류의 원인을 알고 해결책을 찾아야 한다.
1. 문법적 에러를 찾기 위한 에러 메시지 분석
2. 논리적 에러를 찾기 위한 테스트도 중요(중간 중간 print로 확인)

구글과 Stack Overflow는 제일 좋은 스승이다.

📒 <Assignment> Practice


Github의 classroom을 사용해서 과제를 제출하는 법을 알려주셨다.
뛰어난 시스템을 가진 교육은 과제를 제출하는 법도 특별했다.
git clone을 따서 TeamLab에서 커밋을 하면 PR에서 자동으로 채점을 해주었다.
나도 저런 유용한 소프트웨어를 개발하는 사람이 되고 싶다..

📒 <Assignment> basic_math


간단한 수학을 하는 프로그램 과제였다.
크게 4가지의 함수를 구현해서 제출하면 된다.

📝 get_greatest


def get_greatest(number_list):
    """
    주어진 리스트에서 가장 큰 숫자를 반환함

        Parameters:
            number_list (list): integer로 값으로만 구성된 list
            ex - [10, 33, 22, 99, 33]

        Returns:
            greatest_number (int): parameter number_list 중 가장 큰 값

        Examples:
            >>> number_list = [39, 54, 32, 11, 99]
            >>> import basic_math as bm
            >>> bm.get_greatest(number_list)
            99
    """
    greatest_number = max(number_list)
    return greatest_number
max 함수를 사용하여 리스트 내에서 가장 큰 값을 바로 반환해주었다.

📝 get_smallest


def get_smallest(number_list):
    """
    주어진 리스트에서 제일 작은 숫자를 반환함

        Parameters:
            number_list (list): integer로 값으로만 구성된 list
            ex - [10, 33, 22, 99, 33]

        Returns:
            smallest_number (int): parameter number_list 중 가장 작은 값

        Examples:
            >>> number_list = [39, 54, 32, 11, 99]
            >>> import basic_math as bm
            >>> bm.get_smallest(number_list)
            11
    """
    smallest_number = min(number_list)
    return smallest_number
min 함수를 사용하여 리스트 내에서 가장 작은 값을 바로 반환해주었다.

📝 get_mean


def get_mean(number_list):
    """
    주어진 리스트 숫자들의 평균을 구함.

        Parameters:
            number_list (list): integer로 값으로만 구성된 list
            ex - [10, 33, 22, 99, 33]

        Returns:
            mean (int): parameter number_list 숫자들의 평균

        Examples:
            >>> number_list = [39, 54, 32, 11, 99]
            >>> import basic_math as bm
            >>> bm.get_mean(number_list)
            47
    """
    mean = sum(number_list) / len(number_list)
    return mean
평균값은 (총 합 / 크기)이므로, sum과 len을 사용해서 해결했다.

📝 get_median


def get_median(number_list):
    """
    주어진 리스트 숫자들의 중간값을 구함.

        Parameters:
            number_list (list): integer로 값으로만 구성된 list
            ex - [10, 33, 22, 99, 33]

        Returns:
            median (int): parameter number_list 숫자들의 중간값

        Examples:
            >>> number_list = [39, 54, 32, 11, 99]
            >>> import basic_math as bm
            >>> bm.get_median(number_list)
            39
            >>> number_list2 = [39, 54, 32, 11, 99, 5]
            >>> bm.get_median(number_list2)
            35.5
    """
    number_list.sort()
    median = 0.0
    length = len(number_list)
    if length % 2 == 1:
        median = number_list[length // 2]
    else:
        median = (number_list[length // 2] + number_list[length // 2 - 1]) / 2.0
    return median
우선 중간값을 찾기 위해 list를 sort를 사용해서 오름차순으로 정렬해주었다.
그리고 list의 크기가 홀수인 경우와 짝수인 경우를 나누어서 구했다.
홀수인 경우 : 리스트의 길이 / 2 인 index의 값을 바로 반환해주면 된다.
짝수인 경우 : 리스트의 길이 / 2 인 index의 값과 리스트의 길이 / 2 - 1 인 
		index의 값을 더하여, 2로 나누어서 반환해주었다.

첫 과제라서 간단한 문제가 나왔다.

📒 String and advanced function concept


문자열의 기초부터, 함수를 작성할때 고려해야 될 많은 부분을 배울 수 있었다.
좋은 코드를 작성하는 것은 정말 중요한 일이라고 생각한다.
이번 강의에서 배운 내용을 기반으로, 좋은 코드를 쓰는 습관을 가져야 겠다는 생각이 들었다.

📝 String


시퀸스 자료형으로, 문자형 data를 메모리에 저장한다.
영문자 한 글자는 1byte의 메모리 공간을 사용한다.

✏️ 1Byte?

  • 컴퓨터는 2진수로 데이터를 저장한다.
  • 이진수 한 자릿수는 1bit로 저장된다.
  • 즉 1bit는 0또는 1을 가질 수 있다.
  • 1byte = 8bit = 2^8 = 256 까지 저장할 수 있다.
  • 컴퓨터는 문자를 직접적으로 인식하지 않고, 2진수로 인식한다.
  • 이를 위해 2진수를 문자로 변환하는 표준 규칙을 정했다.

✏️ 프로그램 언어에서 데이터 타입

각 타입 별로 메모리 공간을 할당 받는 크기가 다르다.

종류타입크기표현 범위 (32bit)
정수형int4바이트-2^31 ~ 2^31-1
정수형long무제한무제한
실수형float8바이트약 10^-308 ~ 10^308

데이터 타입은 메모리의 효율적 활용을 위해 매우 중요하다.

✏️ 인덱싱과 슬라이싱

리스트와 비슷하게 문자열의 각 문자는 개별 주소(offset)를 가진다.
이 주소를 사용해 할당된 값을 가져오는 것이 인덱싱이다.

>>> a = "abcde"
>>> print(a[0], a[4])
a e
>>> print(a[-1], a[-5])
 e a
>>> print(a[2:])
cde
>>> print(a[:])
abcde
>>> print(a[::-1])
edcba

✏️ 문자열 연산

>>> a = "team"
>>> b = "lab"
>>> print(a + " " + b)
team lab
>>> print(a * 2 + " " + b * 2)
teamteam lablab
>>> 't' in a
True

✏️ 문자열 함수

함수명기능
len(a)문자열의 문자 개수를 반환
a.upper()대문자로 변환
a.lower()소문자로 변환
a.capitalize()첫 문자를 대문자로 변환
a.title()제목 형태로 변환
띄워쓰기 후 첫 글자만 대문자
a.count('abc')문자열 a에 'abc'가 들어간 횟수 반환
a.find('abc')문자열 a에 'abc가 들어간 첫 위치(offset) 반환
a.rfind('abc')문자열 a에 'abc가 들어간 마지막 위치(offset) 반환
a.startswith('abc')문자열 a가 'abc'로 시작하는지 여부 반환
a.endswith('abc')문자열 a가 'abc'로 끝나는지 여부 반환
a.strip()좌우 공백을 없앰
a.rstrip()오른쪽 공백을 없앰
a.lstrip()왼쪽 공백을 없앰
a.split()공백을 기준으로 나눠 리스트로 반환
a.split('abc')abc를 기준으로 나눠 리스트로 반환
a.isdigit()문자열이 숫자인지 여부 반환
a.islower()문자열이 소문자인지 여부 반환
a.isupper()문자열이 대문자인지 여부 반환

📝 Call by ~


함수에서 parameter를 전달하는 방식이다.
되도록 copy를 통해 parameter를 변경하지 말자!

✏️ Call by Value(값에 의한 호출)

함수에 인자를 넘길 때 값만 넘긴다.
함수 내에 인자 값을 변경하더라도, 호출자에게 영향을 주지 않는다.

✏️ Call by Reference(참조에 의한 호출)

함수에 인자를 넘길 때 메모리 주소를 넘긴다.
함수 내에 인자 값을 변경할 때, 호출자의 값도 변경된다.

✏️ Call by Object Reference(객체 참조에 의한 호출)

파이썬은 객체의 주소가 함수로 전달되는 방식을 사용한다.

전달된 객체를 참조하여 변경 시 호출자에게 영향을 주지만,
새로운 객체를 만들 경우 호출자에게 영향을 주지 않는다.

def span(eggs):
	eggs.append(1) # 기존 객체의 주소값에 [1] 추가
	eggs = [2, 3]  # 새로운 객체 생성

>>> ham = [0]
>>> spam(ham)
>>> print(ham)
[0, 1]

📝 Function


✏️ Scoping Rule

변수가 사용되는 범위이다. (함수 또는 메인 프로그램)

  • 지역변수(local variable) : 함수내에서만 사용 가능
  • 전역변수(Global variable) : 프로그램 전체에서 사용 가능
def test():
	x = 10 # local variable
    print(x)
  
>>> x = 20 # global variable
>>> test()
10
>>> print(x)
20

변수 명이 같을 때는 함수 내에서 global으로 선언하면 된다.

✏️ Recursive Function

재귀함수는 자기자신을 호출하는 함수이다.
점화식과 같은 재귀적 수학 모형을 표현할 때 주로 사용된다.
재귀 종료 조건이 반드시 존재해야 하며, 종료 조건까지 함수 호출을 반복한다.

def factorial(n):
	if n == 1 : # 재귀 종료 조건
		return 1
	else:
		return n * factorial(n - 1) # 재귀 함수

✏️ Type hints

Dynamic typing이란 특징 때문에, 처음 함수를 사용하는 사용자가 인터페이스를 알기 어렵다.

# Type hints 문법
def f(var_name : var_type) -> return_tupe

 🔎 Why?

  1. 사용자에게 인터페이스를 명확히 알려줄 수 있다.
  2. 함수의 문서화 시 parameter에 대한 정보를 명확히 알 수 있다.
  3. IDE에서 코드의 발생 가능한 오류를 사전에 확인할 수 있다.
  4. 시스템 전체적인 안정성을 확보할 수 있다.

📝 함수 개발 가이드라인


✏️ Docstring

함수에 대한 상세스펙을 사전에 작성하여 함수 사용자의 이해도를 높인다.
세개의 따옴표로 함수명 아래에 docstring 영역을 표시한다.

def add_binary(a, b):
    ''' 보통 다음과 같이 작성한다.
    Returns the sum of two decimal numbers in binary digit. (목적)
        
        Parameters: (입력 인자)
            a(int) : A decimal integer
            b(int): Another decimal integer
        Returns: (반환 값)
            binary_sum(str): Binary string of the sum of a and b
   '''
   binary_sum = bin(a + b)[2:]
   return binary_sum

 👉 VSC에서 Python Docstring Generator를 사용하면 편리하게 작성해준다.

✏️ 함수 작성 가이드 라인

  • 함수는 가능하면 짧게 작성한다.(줄 수를 줄인다)
  • 함수 이름에 함수의 역할, 의도가 명확히 드러나게 작성한다.
  • 하나의 함수에는 유사한 역할을 하는 코드만 포함시킨다.
  • 되도록 인자로 받은 값 자체를 바꾸지 말고, 임시변수를 선언한다.

✏️ 함수는 언제 만드는가?

  • 공통적으로 사용할 수 있는 코드는 함수로 작성한다.
  • 복잡한 수식은 잘 풀어진 설명으로 함수화 시켜 작성한다.
  • 복잡한 조건도 식별 가능한 이름의 함수로 변환한다.

📝 파이썬 코딩 컨벤션


사람의 이해를 돕기 위해서는 규칙이 필요하다.
그 규칙을 코딩 컨벤션이라고 한다.

✏️ 규칙?

명확한 규칙은 따로 없다. 팀마다, 프로젝트마다 다 다르다.
하지만 중요한 것은 일관성이다. 읽기 좋은 코드가 좋은 코드이다.

  • 들여쓰기는 일반적으로 4 Space를 사용한다. (Tap과 혼합하지만 않으면 된다)
  • 한줄은 최대 79자까지만 제한한다.
  • 불필요한 공백은 최대한 피한다.
  • 연산자는 1칸 이상 띄우지 않는다.
  • 주석은 항상 갱신하며, 불필요한 주석은 삭제한다.
  • 코드의 마지막에는 항상 한 줄을 추가한다.
  • 소문자 l, 대문자 O, 대문자 I는 금지한다.

최근에는 black이라는 모듈을 활용하여 pep8 like 수준을 준수한다.(자동 수정)

📒 <Assignment> text processing


NLP에서 흔히 하는 전처리를 Python으로 작성하는 과제였다.
내장 함수를 사용해서 간단하게 처리할 수 있었다.

📝 normalize


def normalize(input_string):
    """
     인풋으로 받는 스트링에서 정규화된 스트링을 반환함
     아래의 요건들을 충족시켜야함
    * 모든 단어들은 소문자로 되어야함
    * 띄어쓰기는 한칸으로 되어야함
    * 앞뒤 필요없는 띄어쓰기는 제거해야함

         Parameters:
             input_string (string): 영어로 된 대문자, 소문자, 띄어쓰기, 문장부호, 숫자로 이루어진 string
             ex - "This is an example.", "   EXTRA   SPACE   "

         Returns:
             normalized_string (string): 위 요건을 충족시킨 정규회된 string
             ex - 'this is an example.'

         Examples:
             >>> import text_processing as tp
             >>> input_string1 = "This is an example."
             >>> tp.normalize(input_string1)
             'this is an example.'
             >>> input_string2 = "   EXTRA   SPACE   "
             >>> tp.normalize(input_string2)
             'extra space'
    """
    normalized_string = input_string.lower() # 소문자로 변환
    normalized_string = normalized_string.strip() # 좌우 공백 제거
    normalized_string = re.sub(' +', ' ', normalized_string) # 정규표현식으로 중복 공백 제거

    return normalized_string
우선, 전달받은 input_string을 lower() 함수를 통해 소문자로 변환하였다.
그리고 strip() 함수를 사용하여 좌우의 공백을 제거했다.
마지막으로, 정규표현식을 사용해서 공백의 중복된 부분들을 제거해주었다.

📝 no_vowel


def no_vowels(input_string):
    """
    인풋으로 받는 스트링에서 모든 모음 (a, e, i, o, u)를 제거시킨 스트링을 반환함

        Parameters:
            input_string (string): 영어로 된 대문자, 소문자, 띄어쓰기, 문장부호로 이루어진 string
            ex - "This is an example."

        Returns:
            no_vowel_string (string): 모든 모음 (a, e, i, o, u)를 제거시킨 스트링
            ex - "Ths s n xmpl."

        Examples:
            >>> import text_processing as tp
            >>> input_string1 = "This is an example."
            >>> tp.normalize(input_string1)
            "Ths s n xmpl."
            >>> input_string2 = "We love Python!"
            >>> tp.normalize(input_string2)
            ''W lv Pythn!'
    """
    vowel_characters = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']
    no_vowel_string = ""
    for i in input_string:
        if i not in vowel_characters:
            no_vowel_string += i
    return no_vowel_string
우선 vowel_characters를 만들어 모음에 해당되는 대소문자들을 저장해두었다.
그리고 input_string을 순회하면서, vowel_characters에 포함되지 않은 문자면
no_vowel_string에 추가해주었다.

Python의 string function에 대해 알고 있으면 쉽게 풀 수 있는 문제들이었다.

📒 <Assignment> text processing2


동일하게 텍스트의 전처리를 Python으로 작성하는 과제였다.
좋은 코드로 작성하고 싶다는 생각이 들었다.

📝 digits_to_words


def digits_to_words(input_string):
    """
    인풋으로 받는 스트링에서 숫자만 추출하여 영어 단어로 변환하여 단어들이 연결된 스트링을 반환함
    아래의 요건들을 충족시켜야함
    * 반환하는 단어들은 영어 소문자여야함
    * 단어들 사이에는 띄어쓰기 한칸이 있음
    * 만약 인풋 스트링에서 숫자가 존재하지 않는 다면, 빈 문자열 (empty string)을 반환함

        Parameters:
            input_string (string): 영어로 된 대문자, 소문자, 띄어쓰기, 문장부호, 숫자로 이루어진 string
            ex - "Zip Code: 19104"

        Returns:
            digit_string (string): 위 요건을 충족시킨 숫자만 영어단어로 추출된 string
            ex - 'one nine one zero four'

        Examples:
            >>> import text_processing2 as tp2
            >>> digits_str1 = "Zip Code: 19104"
            >>> tp2.digits_to_words(digits_str1)
            'one nine one zero four'
            >>> digits_str2 = "Pi is 3.1415..."
            >>> tp2.digits_to_words(digits_str2)
            'three one four one five'
    """
    number_to_lower = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
    number_list = re.findall(r"\d", input_string)
    digit_list = []
    for num in number_list:
        digit_list.append(number_to_lower[int(num)])
    digit_string = ' '.join(digit_list)
    return digit_string
정규표현식을 사용해서 숫자들을 number_list에 모두 저장했다.
그리고, number_to_lower를 통해 인덱스를 영어 단어로 변환할 수 있게 했다.
그 이후에 digit_list에 변환된 단어들을 하나씩 추가하고,
마지막으로 join 함수를 통해서 digit_string을 만들어 반환했다.

📝 to_camel_case


"""
컴퓨터 프로그래밍에 많은 명명 규칙이 있지만, 두 규칙이 특히 흔히 쓰입니다. 
첫번째로는, 변수 이름을 'underscore'로 나눠준다거나, (ex. under_score_variable)
두번째로는, 변수 이름을 대소문자 구별해 구분자 (delimiter)없이 쓰는 경우가 있습니다. 
이 두번째의 경우에는 첫번째 단어는 소문자로, 그 후에 오는 단어들의 첫번째 글자들은 대문자로 쓰입니다 (ex. camelCaseVariable). 
"""


def to_camel_case(underscore_str):
    """
    이 문제에서 첫번째 규칙 'underscore variable' 에서 두번째 규칙 'camelcase variable'으로 변환함
    * 앞과 뒤에 여러개의 'underscore'는 무시해도 된
    * 만약 어떤 변수 이름이 underscore로만 이루어 진다면, 빈 문자열만 반환해도 됨

        Parameters:
            underscore_str (string): underscore case를 따른 스트링

        Returns:
            camelcase_str (string): camelcase를 따른 스트링

        Examples:
            >>> import text_processing2 as tp2
            >>> underscore_str1 = "to_camel_case"
            >>> tp2.to_camel_case(underscore_str1)
            "toCamelCase"
            >>> underscore_str2 = "__EXAMPLE__NAME__"
            >>> tp2.to_camel_case(underscore_str2)
            "exampleName"
            >>> underscore_str3 = "alreadyCamel"
            >>> tp2.to_camel_case(underscore_str3)
            "alreadyCamel"
    """
    if underscore_str.find('_') == -1:
        return underscore_str
    camelcase_str = underscore_str.lower()
    camelcase_str = camelcase_str.strip('_')
    camelcase_str = re.sub("(_+)([a-z])", lambda x : x.group(2).upper() , camelcase_str)
    return camelcase_str
전처리로, '_'가 하나도 없다면 Camel로 판단하고 바로 반환했다.
만약 입력받은 단어의 앞과 뒤에 있는 불필요한 _를 제거해주었다.
그리고 모든 글자들을 소문자로 바꾸어줬다.
이 후 정규표현식을 사용해서 1개 이상의 _ 뒤에 붙은 소문자를 대문자로 변환해주었다.

정규 표현식을 공부하고 푸느라 생각보다 시간이 오래 걸렸다.
string 처리에서 정규 표현식은 절대적으로 뛰어난 것 같다.

📒 <Assignment> Baseball


숫자 야구를 Python으로 구현해야 되는 과제였다.
로직 자체는 아주 간단했다.
입/출력 전처리 할 내용이 많았다.

📝 is_digit


def is_digit(user_input_number):
    # '''
    # Input:
    #   - user_input_number : 문자열 값
    # Output:
    #   - user_input_number가 정수로 변환 가능할 경우는 True,
    #     그렇지 않을 경우는 False
    # Examples:
    #   >>> import baseball_game as bg
    #   >>> bg.is_digit("551")
    #   True
    #   >>> bg.is_digit("103943")
    #   True
    #   >>> bg.is_digit("472")
    #   True
    #   >>> bg.is_digit("1032.203")
    #   False
    #   >>> bg.is_digit("abc")
    #   False
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당
    result = user_input_number.isdecimal()

    # ==================================
    return result
간단하게 isdecimal() 함수를 사용해서 해결했다.

📝 is_between_100_and_999


def is_between_100_and_999(user_input_number):
    # '''
    # Input:
    #   - user_input_number : 문자열 값
    #                         입력된 값은 숫자형태의 문자열 값임이 보장된다.
    # Output:
    #   - user_input_number가 정수로 변환하여 100이상 1000미만일 경우 True,
    #     그렇지 않을 경우는 False
    # Examples:
    #   >>> import baseball_game as bg
    #   >>> bg.is_between_100_and_999("551")
    #   True
    #   >>> bg.is_between_100_and_999("103943")
    #   False
    #   >>> bg.is_between_100_and_999("472")
    #   True
    #   >>> bg.is_between_100_and_999("0")
    #   False
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당
    result = int(user_input_number) >= 100 and int(user_input_number) < 1000

    # ==================================
    return result
조건 그대로 범위를 비교해서 True or False를 반환했다.

📝 is_duplicated_number


def is_duplicated_number(three_digit):
    # '''
    # Input:
    #   - three_digit : 문자열로 된 세자리 양의 정수 값
    #                   문자열로 된 세자리 양의 정수값의 입력이 보장된다.
    # Output:
    #   - three_digit 정수로 변환하였을 경우 중복되는 수가 있으면 True,
    #     그렇지 않을 경우는 False
    #   ex) 117 - True, 123 - False, 103 - False, 113 - True
    # Examples:
    #   >>> import baseball_game as bg
    #   >>> bg.is_duplicated_number("551")
    #   True
    #   >>> bg.is_duplicated_number("402")
    #   False
    #   >>> bg.is_duplicated_number("472")
    #   False
    #   >>> bg.is_duplicated_number("100")
    #   True
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당

    sorted_digit = sorted(three_digit)
    result = sorted_digit[0] == sorted_digit[1] or sorted_digit[1] == sorted_digit[2]
    # ==================================
    return result
문자열이므로, 편한 비교를 위해 정렬하였다.
가운데 값이 왼쪽 혹은 오른쪽 값과 같으면 적어도 2개의 수가 똑같은 것이다.
parameter 값을 변경하지 않는게 좋다고 해서, sorted를 사용했다.

📝 is_validated_number


def is_validated_number(user_input_number):
    # '''
    # Input:
    #   - user_input_number : 문자열 값
    # Output:
    #   - user_input_number 값이 아래 조건이면 True, 그렇지 않으면 False를 반환
    #        1) 숫자형 문자열이며, 2) 100이상 1000미만이며, 3) 중복되는 숫자가 없을 경우
    # Examples:
    #   >>> import baseball_game as bg
    #   >>> bg.is_validated_number("amvd")
    #   False
    #   >>> bg.is_validated_number("402")
    #   True
    #   >>> bg.is_validated_number("472")
    #   True
    #   >>> bg.is_validated_number("100")
    #   False
    #   >>> bg.is_validated_number("1000")
    #   False
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당

    result = is_digit(user_input_number) and is_between_100_and_999(user_input_number) and not is_duplicated_number(user_input_number)
    # ==================================
    return result
위에 만든 3개의 함수의 and 연산을 해주었다.

📝 get_not_duplicated_three_digit_number


def get_not_duplicated_three_digit_number():
    # '''
    # Input:
    #   - None : 입력값이 없음
    # Output:
    #   - 중복되는 숫자가 없는 3자리 정수값을 램덤하게 생성하여 반환함
    #     정수값으로 문자열이 아님
    # Examples:
    #   >>> import baseball_game as bg
    #   >>> bg.get_not_duplicated_three_digit_number()
    #   125
    #   >>> bg.get_not_duplicated_three_digit_number()
    #   634
    #   >>> bg.get_not_duplicated_three_digit_number()
    #   583
    #   >>> bg.get_not_duplicated_three_digit_number()
    #   381
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당
    # get_random_number() 함수를 사용하여 random number 생성

    result = get_random_number()
    while is_duplicated_number(str(result)):
        result = get_random_number()
    # ==================================
    return result
중복되지 않는 수가 나올때까지, while문에서 get_random_number()를 진행하였다.

📝 get_strikes_or_ball


def get_strikes_or_ball(user_input_number, random_number):
    # '''
    # Input:
    #   - user_input_number : 문자열값으로 사용자가 입력하는 세자리 정수
    #   - random_number : 문자열값으로 컴퓨터가 자동으로 생성된 숫자
    # Output:
    #   - [strikes, ball] : 규칙에 따라 정수형 값인 strikes와 ball이 반환됨
    #   변환 규칙은 아래와 같음
    #   - 사용자가 입력한 숫자와 컴퓨터가 생성한 숫자의
    #     한 숫자와 자릿수가 모두 일치하면 1 Strike
    #   - 자릿수는 다르나 입력한 한 숫자가 존재하면 1 Ball
    #   - 세자리 숫자를 정확히 입력하면 3 Strike
    # Examples:
    #   >>> import baseball_game as bg
    #   >>> bg.get_strikes_or_ball("123", "472")
    #   [0, 1]
    #   >>> bg.get_strikes_or_ball("547", "472")
    #   [0, 2]
    #   >>> bg.get_strikes_or_ball("247", "472")
    #   [0, 3]
    #   >>> bg.get_strikes_or_ball("742", "472")
    #   [1, 2]
    #   >>> bg.get_strikes_or_ball("472", "472")
    #   [3, 0]
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당

    result = [0, 0]
    for i in range(3):
        for j in range(3):
            if user_input_number[i] == random_number[j]:
                result[i != j] += 1                  
    # ==================================
    return result
[strike, ball]의 count를 갖는 list인 result를 만들었다.
i의 0~2번째 index와 j의 0~2번째 index를 2중 반목문으로 순회하였다.
만약 두 값이 같다면 i와 j가 같은 경우는 result[0], 다른 경우는 result[1]을 증가시켰다.

📝 is_yes


def is_yes(one_more_input):
    # '''
    # Input:
    #   - one_more_input : 문자열값으로 사용자가 입력하는 문자
    # Output:
    #   - 입력한 값이 대소문자 구분없이 "Y" 또는 "YES"일 경우 True,
    #     그렇지 않을 경우 False를 반환함
    # Examples:
    #   >>> import baseball_game as bg
    # >>> bg.is_yes("Y")
    # True
    # >>> bg.is_yes("y")
    # True
    # >>> bg.is_yes("Yes")
    # True
    # >>> bg.is_yes("YES")
    # True
    # >>> bg.is_yes("abc")
    # False
    # >>> bg.is_yes("213")
    # False
    # >>> bg.is_yes("4562")
    # False
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당

    result = one_more_input.lower() in ['y', 'yes']
    # ==================================
    return result
입력받은 one_more_input을 lower()함수를 이용해 변환시켰다.
이후에는 'y', 'yes'와만 비교해보면 된다.

📝 is_no


def is_no(one_more_input):
    # '''
    # Input:
    #   - one_more_input : 문자열값으로 사용자가 입력하는 문자
    # Output:
    #   - 입력한 값이 대소문자 구분없이 "N" 또는 "NO"일 경우 True,
    #     그렇지 않을 경우 False를 반환함
    # Examples:
    #   >>> import baseball_game as bg
    # >>> bg.is_no("Y")
    # False
    # >>> bg.is_no("b")
    # False
    # >>> bg.is_no("n")
    # True
    # >>> bg.is_no("NO")
    # True
    # >>> bg.is_no("nO")
    # True
    # >>> bg.is_no("1234")
    # False
    # >>> bg.is_no("yes")
    # False
    # '''
    # ===Modify codes below=============
    # 조건에 따라 변환되어야 할 결과를 result 변수에 할당

    result = one_more_input.lower() in ['n', 'no']
    # ==================================
    return result
입력받은 one_more_input을 lower()함수를 이용해 변환시켰다.
이후에는 'n', 'no'와만 비교해보면 된다.

📝 main


def main():
    print("Play Baseball")
    stop_game = False
    while not stop_game:
        user_input = 999
        random_number = str(get_not_duplicated_three_digit_number())
        print("Random Number is : ", random_number)
        # ===Modify codes below=============
        # 위의 코드를 포함하여 자유로운 수정이 가능함
        # ==================================
        while True:
            user_input = input("Input guess number : ")
            if user_input == '0':
                stop_game = True
                break
            if not is_validated_number(user_input):
                print("Wrong Input, Input again")
                continue
            strike, ball = get_strikes_or_ball(user_input, random_number)
            print(f'Strikes : {strike}, Balls : {ball}')
            if strike == 3:
                break
        if stop_game:
            break
        while True:
            more_user_input = input("You win, one more(Y/N)?")
            if(is_yes(more_user_input)):
                break
            elif(is_no(more_user_input)):
                stop_game = True
                break
            print("Wrong Input, Input again")

    print("Thank you for using this program")
    print("End of the Game")
그냥 문제를 순차적으로 풀어나가면 된다.
stop_game이 True가 될 때까지 게임이 진행된다.
이는, 'N'를 입력한 경우와 '0'을 입력한 경우에 True가 된다.

게임이 진행되면 user_input을 받는다.
잘못된 값을 입력했다면, 에러 메시지를 출력하고 다시 반복문의 처음으로 돌아간다.
올바른 수를 입력하면 get_strikes_or_ball()함수를 통해 strike와 ball의 count를 센다.
3 strike인 경우는 정답을 맞춘 경우이므로 이번 게임을 종료한다.

게임이 종료되면 한 번 더 게임을 할지 물어본다.
만약, 게임을 계속 한다면 위 반복문으로 돌아간다.
그렇지 않은 경우는 게임을 종료한다.

test case의 코드도 굉장히 신기해서 이제 공부를 해 볼 예정이다.
문제의 설명이 그렇게 친절하지 않아서 탈출 조건, 입출력 등에서 몇 번 틀렸다.
함수 하나 하나를 작성하는 것은 앞선 문제들보다 훨씬 쉬운 문제였다.

profile
Beginner

0개의 댓글