본문 바로가기

SK네트웍스 Family AI캠프 10기/Daily 회고

6일차. 함수 & 클래스

더보기

 

6일 차 회고.

 

 매일 오늘은 일찍 자야지 다짐해도 자려고 누울 때마다 아쉬워서 일부러 더 깨어있어서 요즘 피곤하다. 이건 진짜 고쳐야 할 것 같다. 그리고 토이 프로젝트에 참여하기로 했는데, 열심히 해볼 생각이다. 먼저, 깃에 대해서 강의를 들어야 할 것 같다. 그리고 프로젝트를 구체화하기 위해서 더 생각해봐야 한다. 

 

 

 

 

0. 복습

 

 

0-0. 가상환경 구축

 

py -3.13 -m venv .venv			# 가상환경 생성
.\.venv\Scripts\activate		# 가상환경 활성화
python -m pip install --upgrade pip	# pip 업그레이드
pip install jupyter			# jupyter 설치

 

 

0-1. 묵찌빠 게임 - 가위바위보 게임 수정

 

import enum

class GAME(enum.Enum):
    가위 = {
        '바위': '패배',
        '보': '승리'
    }
    바위 = {
        '가위': '승리',
        '보': '패배'
    }
    보 = {
        '가위': '패배',
        '바위': '승리'
    }

 

class UndefinedValue(Exception):
    def __init__(self):
        super().__init__("Undefined Value.")

 

import random

def value_fixed(name, who):		# value_fixed(): 각 변수에 값 고정
    who = GAME[who]
    print(f"{name} : {who.name}")
    return who

def user_value():			# user_value(): USER의 묵찌빠 게임 값 입력
    user = input("USER : [ 가위 | 바위 | 보 ] 중에 입력하세요.")
    user = user.strip()
    if user not in GAME.__members__:
        print("USER : 잘못 입력하였습니다.")
        raise UndefinedValue
    user = value_fixed("USER", user)
    return user

def computer_value():			# computer_value(): COMPUTER의 묵찌빠 게임 값 설정
    computer = random.choice(list(GAME.__members__.keys()))
    computer = value_fixed("COMPUTER", computer)
    return computer

def game_result(user, computer):	# game_result(): 묵찌빠 게임 결과 출력
    print(f"User가 {GAME[user].value[computer]}했습니다.")

def game():				# game(): 묵찌빠 게임 진행
    i = 0
    user_result = list()
    computer_result = list()

    while True:
        try:
            print(f"{i + 1}번째 행동")
            user = user_value()
            computer = computer_value()
            user_result.append(user.name)		# user_result에 user의 값 저장
            computer_result.append(computer.name)	# computer_result에 computer의 값 저장
            print("")

            if user_result[i] == computer_result[i]:
                break

            i += 1

        except Exception as e:
            print(e)
    
    if i == 0:
        print("게임을 다시 시작하세요.")
    else:
        game_result(user_result[i - 1], computer_result[i - 1])

game()

 

 

 

1. 함수(Function)

 

 

1-1. 이터레이터(Iterator)

 

이터레이터는 반복이 가능한 객체를 next() 함수를 통해 다음 값을 반환한다.

한 번에 하나의 요소만 메모리에 유지하기 때문에 메모리를 효율적으로 사용할 수 있다.

따라서 대용량 데이터를 처리할 때 유용하다.

또한, 필요한 요소만 생성하기 때문에 지연(lazy evaluation)을 지원하고, 내장 함수와 함께 사용이 가능하다.

 

a = [1, 2, 3]
a_iter = iter(a)	# iter(): list를 iter로 변환

type(a)			# list_iterator

for i in a_iter:
    print(i)
# 1
# 2
# 3

 

 

1-2. 제너레이터(Generator)

 

제너레이터는 이터레이터를 생성한다. 제너레이터 함수를 호출해도 실행되지 않으며, next() 함수를 사용하여 실행한다.

여기서 제너레이터는 yield 키워드를 사용한다.

def gener():
    for i in [1, 2, 3]:
        yield i	# yield 사용

g = gener()
type(g)		# generator

for i in g:
    print(i)
# 1
# 2
# 3

 

 

 

2. 모듈

 

 

.py 파일을 만들어 이를 외부에서 호출하면 모듈이 된다.

외부에서 .py 파일 속에 있는 함수를 호출하는 방법은 다음과 같다.

# ex01.py

def add(a, b):
    return a + b

def add_one(a):
    return a + 1

 

여기서 어노테이션(annotation)은 사용자나 프로그램에 유용한 정보를 전달하기 위한 목적으로 사용되는 것이다.

어노테이션을 통해 자료형의 예상 타입을 지정할 수 있다. 하지만 이를 지키지 않는다고 에러가 발생하지는 않는다.

# common\utils.py

import .constant import TEST

def get_test(p_test:TEST) -> str:	# annotation
    return p_test.name

def add(a:int, b:int) -> int:
    return a + b

 

# common\constant.py

import enum

class TEST(enum.Enum):
    A = enum.auto()
    B = enum.auto()
    C = enum.auto()

 

import ex01
from ex01 import add, add_one

from common import utils as u
from common.constant import TEST

ex01.add_one(10)	# 11
add_one(20)		# 21

u.add(1, 2)		# 3
u.get_test(TEST.A)	# 'A'

 

 

 

3. 클래스(Class)

 

 

3-1. 클래스 생성

 

클래스는 변수와 함수를 묶어놓은 것으로, 객체를 만들기 위해 사용한다.

클래스를 메모리에 객체화한 것을 인스턴스(instance)라고 한다.

클래스 내부의 함수는 첫 번째 매개변수로 반드시 self를 입력해야 한다.

class GrandMother:		# GramdMother: Class
    family = "grandparents"	# family: Attribute / grandparents: Statement
    name = ""
    age = 0
    
    def __init__(self, p_name, p_age):		# __init__(): Initialized Method
        self.name = p_name
        self.age = p_age
    
    def print_self(self):	# print_self(): Method
        print(self)
    
    def print_hello():		# print_hello(): Class Function
        print("Hello")
        
LEE = GrandMother()		# LEE: Instance / GrandMother(): Constructor

 

클래스를 객체화하여 인스턴스를 생성하면, 같은 클래스여도 다른 객체로 서로 다른 메모리에 저장된다.

GM1 = GrandMother('A', 10)
print(GM1.print_self())
# <__main__.GrandMother object at 0x0000015C4CDA91D0>

GM2 = GrandMother('B', 20)
print(GM2.print_self())
# <__main__.GrandMother object at 0x0000015C4CDA8CD0>

 

클래스 함수는 self 매개변수가 없으며, 객체화한 인스턴스에서는 사용할 수 없다.

print(GrandMother.print_hello())
# Hello

print(GM1.print_hello())
# TypeError

 

 

3-2. 기사 vs. 마법사 게임

 

import random

class Knight:
    hp = 0
    mp = 0

    def __init__(self, hp=100, mp=0):
        self.hp = hp
        self.mp = mp
    
    def attack(self) -> int:
        attack_amount = random.randint(30, 50)
        print(f"Knight | Attack: {attack_amount}")
        return attack_amount
    
    def defend(self, attack_amount):
        if random.random() > 0.5:
            print(f"Knight | Defend Success, hp: {self.hp}")
            return
        
        self.hp -= attack_amount
        print(f"Knight | HP: {self.hp}")
        if self.hp <= 0:
            print("Knight | Defeat")

class Mage:
    hp = 0
    mp = 0

    def __init__(self, hp = 50, mp = 100):
        self.hp = hp
        self.mp = mp

    def attack(self):
        attack_amount = random.randint(60, 100)
        if self.mp < attack_amount:
            attack_amount = self.mp
        print(f"Mage | Attack: {attack_amount}")
        self.mp -= attack_amount
        return attack_amount
    
    def defend(self, attack_amount):
        if random.random() > 0.5:
            print(f"Mage | Defend Success")
            return
        
        self.hp -= attack_amount
        print(f"Mage | HP: {self.hp}")
        if self.hp <= 0:
            print("Mage | Defeat")

 

knight = Knight()
mage = Mage()

print("-" * 33)
print("")
print("Initial Statement")
print(f"Knight HP: {knight.hp}")
print(f"Mage HP: {mage.hp}")
print("")
print("-" * 33)

i = 1

while True:
    print("")
    print(f"Turn: {i}\n")
    knight_attack = knight.attack()

    mage.defend(knight_attack)
    if mage.hp <= 0:
        print("Game End")
        break

    mage_attack = mage.attack()

    knight.defend(mage_attack)
    if knight.hp <= 0:
        print("Game End")
        break
    
    i += 1
    print("")
    print("-" * 33)

 

 

3-3. 상속(Inheritance)

 

상속을 통해 기존 클래스를 확장하고 재사용할 수 있다.

여기서 기반이 되는 클래스는 부모 클래스이고, 이를 상속받아 확장한 것을 자식 클래스라고 한다.

자식 클래스는 부모 클래스의 변수와 함수를 사용할 수 있지만,

부모 클래스는 자식 클래스의 변수와 함수를 사용할 수 없다.

class Parent:		# 부모 클래스 정의
    name = "Parent"
    
    def print_name(self):
        print(self.name)
    
class Child(Parent):	# 자식 클래스 정의
    age = 20
    
    def print_age(self):
        print(self.age)

parent1 = Parent()
parent1.print_name()	# Parent
parent1.print_age()	# AttributeError

child1 = Child()
child1.print_name()	# Parent
child1.print_age()	# 20