본문 바로가기
DEV/파이썬 이론

파이썬 코딩 :: 파이썬 클래스, 숫자 야구 만들기_TIL#10

by 올커 2022. 9. 13.

■ JITHub 개발일지(TIL : Today I Learned) 10일차


 

□  TIL ::

     파이썬 주요 문법, 클래스(계산기, 도형넓이, 프로필), mutable/immutable, 숫자야구


1. 클래스 기본 개념

 - 클래스를 선언하는것은 과자 틀을 만드는 것

   : 선언된 과자틀(class)로 과자(instance)를 만드는 것으로 자주 비유되기도 한다.
 - 클래스는 인스턴스를 생성하여 사용한다. (*함수의 경우 선언 후 바로 사용)
 - class 내부에 선언되는 메소드는 기본적으로 self라는 인자를 갖고 있으며 self는 전역변수의 속성을 가지고 있다.

 *용어
 - 인스턴스(instance) : class를 사용해 생성된 객체을 말한다.
 - 메소드(method) : 메소드란 클래스 내에 선언된 함수이며, 클래스 함수라고도 한다.
 - self : 메소드를 선언할 때에는 항상 첫번째 인자로 self를 넣어줘야 한다.

 

2. 클래스를 사용한 도형 넓이 계산기 (Area calculator)

# 도형 넓이 계산기
import math

class Area:
    def __init__(self, a, b):
        print("**도형 넓이 계산기**")
        self.a = a
        self.b = b
    
    def square(self):
        area = self.a * self.b
        return area
    
    def triangle(self):
        area = self.a * self.b / 2
        return area
    
    def circle(self):
        area = math.pi *(self.a**2)
        return area
    

area = Area(10, 20)
print(area.square()) # 사각형의 넓이
print(area.triangle()) # 삼각형의 넓이
print(area.circle()) # 원의 넓이

 

3. 클래스를 사용한 계산기 (Calculator)

# 계산기 만들어보기(with class)
class Calc:
    # def __init__(self, a, b):
    #     self.a = a
    #     self.b = b

    def set_number(self, a, b):
        self.a = a
        self.b = b
        
    def plus(self):
        sum = self.a + self.b
        return sum

    def minus(self):
        dif = self.a - self.b
        return dif
    
    def multiple(self):
        mul = self.a * self.b
        return mul
    
    def divide(self):
        div = self.a / self.b
        return div
    
    
calc = Calc()
calc.set_number(20, 10)
print(calc.plus()) # 더한 값
print(calc.minus()) # 뺀 값
print(calc.multiple()) # 곱한 값
print(calc.divide()) # 나눈 값

 

4. 클래스를 사용한 프로필 관리 기능 만들기 (User profile)

# 프로필 관리 기능 만들어보기
class Profile():
    def __init__(self):
        self.profile = {
            "name": "-",
            "gender": "-",
            "birthday": "-",
            "age": "-",
            "phone": "-",
            "email": "-",
        }
    
    def set_profile(self, profile):
        self.profile = profile

    def get_profile(self):
        return self.profile

    def get_name(self):
        return self.profile["name"]

    def get_gender(self):
        return self.profile["gender"]

    def get_birthday(self):
        return self.profile["birthday"]
    
    def get_age(self):
        return self.profile["age"]
    
    def get_phone(self):
        return self.profile["phone"]

    def email(self):
        return self.profile["email"]

profile = Profile()
profile.set_profile({
    "name": "lee",
    "gender": "man",
    "birthday": "01/01",
    "age": 32,
    "phone": "01012341234",
    "email": "python@sparta.com",
})

print(profile.get_name()) # 이름 출력
print(profile.get_gender()) # 성별 출력
print(profile.get_birthday()) # 생일 출력
print(profile.get_age()) # 나이 출력
print(profile.get_phone()) # 핸드폰번호 출력
print(profile.email()) # 이메일 출력

 

5. mutable, immutable

 - mutable은 값이 변한다는 의미이며, immutable은 값이 변하지 않는다는 의미를 갖고 있다.

 - int, str, list 등 자료형은 각각 mutable 혹은 immutable한 속성을 가지고 있다.

   (1) immutable 속성을 가진 자료형 : int, float, str, tuple

   (2) mutable 속성을 가진 자료형 : list, dict

 

※ 아래 코드를 통해 mutable과 immutable의 차이를 비교해볼 수 있다.

immutable = "String is immutable!!"
mutable = ["list is mutable!!"]
 
string = immutable
list_ = mutable

string += " immutable string!!"
list_.append("mutable list!!")

print(immutable)
print(mutable)
print(string)
print(list_)

# result print
"""
String is immutable!!
['list is mutable!!', 'mutable list!!']
String is immutable!! immutable string!!
['list is mutable!!', 'mutable list!!']
"""

 - 변수 mutablelist_는 리스트 자료형으로써 mutable한 속성을 갖고 있고, 할당하는 메모리의 주소를 참조하기 때문에 이후에 list_가 8번째 줄의 list_.append("mutable list!!")로 인해 변경되면서 주소에 할당된 값이 바뀌고, 같은 주소를 바라보고 있는 변수 mutable의 값도 같이 변경된다.

 - 위와 같은 경우를 피하고 값만 복사하고 싶을 경우 deepcopy 또는 인덱스를 가져와 새로운 리스트를 만들어주는 방법을 사용할 수 있다.

from copy import deepcopy

mutable = ["hello"]

# 아래 세 가지의 차이
list_ = mutable		# 1번방법

list_.append("mutable test!")
# 이때 list_와 mutable은 mutable 속성으로 위의 식으로 인해 값이 둘 다 변화된다

# 값만 할당하며, mutable의 값은 바뀌지 않는다.
list_ = deepcopy(mutable)		# 2번방법
list = mutable[::]		# 3번방법

 

6.  숫자야구 만들기에서 사용된 주요 문법

  - random 모듈과 random.shuffle()을 활용한 리스트 섞기

# 난수 생성, 임의의 번호 생성 등 랜덤한 동작이 필요할 때 사용된다.
import random

numbers = [1, 2, 3, 4, 5, 6, 7, 8]
random.shuffle(numbers) # numbers를 무작위하게 섞기
print(numbers) # [2, 8, 6, 4, 3, 7, 1, 5]

 

 - 리스트 축약식(for문) 사용

# 리스트 컴플레이션, 축약식
number_list = [x for x in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 - pop은 괄호 안에 아무것도 없다면 기본적으로 가장 마지막 값을 빼고, 숫자를 지정하면 원하는 인덱스의 값을 추출하고 할당할 수 있다.

# 리스트 컴플레이션, 축약식
number_list = [x for x in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
random_number = number_list.pop(5) 		# pop을 통해 5번 인덱스의 값을 뺀다.

print(number_list)
print(random_number)

 - pop을 사용해서 5가지 랜덤한 숫자 리스트 생성하기 다른 방법

# 리스트 컴플레이션, 축약식
length = 5

number_list = [x for x in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

random_number = []

for _ in range(length):
	random_number.append(number_list.pop(random.randrange(0, len(number_list))))

print(number_list)
print(random_numbers)

 

length = 5
random_numbers = set() # set타입으로 random_numbers를 하나 만들기

while len(random_numbers) < length:
	random_numbers.add(random.randint(0, 9))

 

※ randrange와 randint의 차이점 : randrange는 마지막 숫자를 포함하지 않지만, randint는 마지막 숫자를 포함한다.

 -  set 자료형 만들때 주의할 점. 

    변수 정의할 때 중괄호'{}'만 사용하면 딕셔너리 자료형이 된다.

    set자료형으로 만들기 위해서는 'set()'을 사용해야 한다.

dict_a = {}

set_a = set()

 - set자료형은 작은 숫자(한 자리수)는 자동으로 정렬을 해주는 속성이 있지만, 두 자리 이상의 숫자부터는 정렬을 하지 않는 속성이 있음을 주의해야 한다.

 

length = 5
random_numbers = set() # set타입으로 random_numbers를 하나 만들기

while len(random_numbers) < length:
	random_numbers.add(random.randint(0, 9))
    
random_numbers = list(random_numbers)
random.suffle(random_numbers)
print(random_numbers)

 

 - 프로그램이 시작된 시간 기록하기 : time.time()

start_time = time.time()

 - for문을 사용하여 인덱스와 리스트 출력하기, enumerate

import random
import time
import datetime

def main()
length = input("자릿수를 입력해주세요 :")
random_numbers = set() # set타입으로 random_numbers를 하나 만들기

while len(random_numbers) < int(length):
	random_numbers.add(random.randint(0, 9))

random_numbers = list(random_numbers)
random.suffle(random_numbers)

start_time = time.time()
try_count = 0

while True:
	input_number = int(input())
    
    if input_number == "exit":
    	return
	try_count += 1
    out_count = 0
    
	ball_count = 0
    strike_count = 0

    for i, v in enumerate(input_number):
        v = int(v)
        if v not in random_numbers: #포함되어있지 않은 경우
            out_count += 1
        else : # 포함되어 있는 경우
            if random_numbers[i] == v:
                strike_count += 1
            else:
                ball_count += 1
                
	if strike_count == length:
    	print("####################################")
        print("정답입니다!")
        print(f"소요시간 : {time.time() = start_time:.2f}")
        print(f"클리어 일자 : {date_time.now()}")
        print(f"도전 횟수 : {try_count}")
        print("####################################")
        return
        
    print(f"{ball_count}볼 {strike_count}스트라이크 {out_count}아웃")
                
main()

 

 - 개발용일때와 릴리즈용일때 로그를 다르게 찍는 방법

   릴리즈 할 때에는 DEBUG를 False라고 넣으면 [DEBUG]를 표현하지 않고 내용을 찍는다.

DEBUG = True

def log(message):
	if DEBUG:
    	print(f"[DEBUG] {message}")

 - 로그 레벨 5가지(DEBUG, VERBOSE, INFO, WARNING, ERROR)

LOG LEVEL

DEBUG
VERBOSE
INFO
WARNING
ERROR

 

 


■ TIT :: Today I thought

 - 파이썬 클래스는 개념이 생소해서 익히기가 쉽지 않은 것 같다. 잊지 않도록 자주 사용해보고, 개념을 자주 보아서 익숙해지도록 해야겠다.

 - mutable/immutable 속성 역시 메모리라는 개념이 새로 나와서 쉽지 않았다. 잊지 않도록 Check!

 - 숫자야구 풀이는 이전에 내가 만들었던 풀이와 다른 부분이 꽤나 있었다. 두 코드를 잘 보고 어떤 부분을 다르게 표현했는지, 그리고 남이 짠 코드를 내가 똑같이 다시 작성해보는 것도 도움이 많이 될 것 같다.

반응형

댓글