728x90
SMALL
- 오늘은 함수, 모듈, 클래스에 대한 이론을 배우고, 해당 내용을 토대로 Spyder에서의 실습을 진행했습니다.
🥱 함수
- 우리가 함수를 만들어야 하는 이유는 총 3가지가 있습니다!
첫 번째는 중복 코드 방지
두 번째는 코드의 유지 보수
마지막으로 개발의 생산성
- 간단히만 얘기해 별로 중요하지 않게 보일 수도 있겠지만, 이는 프로그램 설계, 모델 설계, 서비스 구현 등에 있어서 굉장히 중요한 부분을 차지하고 있기 때문에 함수를 설계할 때에는 심도 있게 고민하셔야 합니다.
- 함수는 반드시 독립적으로 한 가지의 일만 수행할 수 있도록 설계되어야 합니다.
- 함수를 정의하려면 def 키워드를 사용해야 하고, 그 키워드 다음에 함수의 기능과 연관된 적당한 함수명이 지정되어야 합니다.
- 함수 내부의 변수들은 함수가 호출되었을 때는 사용 가능하지만, 함수가 종료되면 더 이상 사용할 수 없게 됩니다.
✨ 함수의 종류
- 함수의 종류는 크게 위 이미지와 같이 총 4가지로, 매개변수의 유뮤와 반환값의 유무에 따라 달라집니다.
- 함수를 호출할 때 "NameError: name 'function' is not defined"가 출력된다면, 정의한 함수가 메모리에 올려가지 않은 상태에서 호출되었다는 뜻입니다.
- 또한, "TypeError: function() takes 0 positional arguments but 1 was given"와 같은 오류가 출력되면 정의한 함수가 매개변수를 받을 수 없는 형태라는 것이므로 매개변수가 들어갈 수 있게 함수를 수정해야 합니다.
✨ 함수 호출 과정
- 예를 들어 아래와 같이 특정 주식의 종가가 주어지면 상한가를 계산해주는 함수가 있다고 해보겠습니다.
def cal_upper(price):
increment = price * 0.3
upper_price = price + increment
return upper_price
print(cal_upper(10000))
- 사용자가 cal_upper 함수를 호출하게 되면, 호출 단계에서는
- 함수에 매개변수 자리에 위치해있는 'price' 변수가 매개변수 값 10000을 할당받게 되고,
- 이 입력된 매개변수 값은 컴퓨터 메모리의 어딘가에 할당됩니다.
- 함수의 실행 단계에서는,
- 함수에 정의되어 있는 수행 문장들이 차례대로 실행됩니다.
- 여기서 increment와 upper_price가 계산되어 할당되고, 이 변수들이 실제 메모리에 저장됩니다.
- 마지막으로 함수의 종료 단계에서는,
- 할당된 변수와 메모리가 더 이상 사용되지 않기 때문에 관련 모든 메모리는 해제됩니다.
- 글로만 작성하니 이해하기 어려울 수 있어 아래 그림으로 한 번 표현해봤습니다.
- 그림은 OS, 실행 환경에서의 메모리 관리까지 포함시켜 총체적인 내용이 담겨 있습니다.
- 가비지 컬렉션 관련 내용은 별도의 포스팅에서 보완시켜 작성해 보겠습니다.
✨ 파이썬 내장 함수
💡 abs(x)
- 정수형 또는 실수형 값을 입력받은 후 해당 값의 절댓값을 반환해주는 함수입니다.
- 예를 들어, abs(-3)을 입력하게 되면 3이 반환됩니다.
💡 chr(i)
- 유니코드 값을 입력받으면, chr() 함수는 그 값에 해당하는 문자열을 반환해줍니다.
- 예를 들어, 아스키 코드에서 알파벳 소문자 a는 97이기에 chr(97)을 입력하게 되면 'a'가 반환됩니다.
💡 enumerate(iterable, start=0)
for i, stock in enumerate(['Naver', 'KaKao', 'SK']):
print(i, stock)
# 출력값
# 0 Naver
# 1 KaKao
# 2 SK
- 입력으로 시퀀스 자료형(리스트, 튜플, 문자열)을 주게 되면 enumerate 객체를 반환하게 되는데, 이 객체에는 시퀀스 자료형 내의 값과 인덱스가 들어있습니다.
💡 id(object)
- 객체를 입력받아 해당 객체의 고유값을 반환하는데, 보통 이 고유값은 객체가 할당된 메모리의 주소 값을 의미합니다.
- 두 변수의 id() 함수 반환값이 같은 경우, 두 변수는 서로 같은 객체를 할당하고 있음을 의미합니다.
📲 모듈
- 모듈은 함수보다 더 큰 단위의 코드 묶음입니다. 이 모듈에는 여러 함수, 변수 등이 선언될 수 있습니다.
- 파이썬 파일을 만들게 되면, 파일명.py로 만들어지게 되는데, 여기서 사용되는 '파일명'이 import할 수 있는 모듈의 이름입니다.
✨ time 모듈
- 이 모듈을 다루는 것에 우선 익숙해지기 위해 먼저 파이썬에서 시간을 다루는 time 모듈을 실습해 보았습니다.
- 그 전에! time 모듈은 파이썬 언어 자체에 내장되어 있는 내장 모듈(built-in 모듈)입니다.
💡 time.time() → float
- time() 함수는 1970년 1월 1일 0시 0분 0초(UTC)부터 현재까지의 경과 시간을 초 단위로 변환해 반환해줍니다.
- 여기서 왜 1970년부터인지는 아직 의견이 분분하다고 합니다.
💡 time.ctime([secs])
import time
current_time = time.ctime()
print(current_time)
print(current_time.split()[-1])
# 출력값
# Tue Feb 4 12:10:36 2025
# 2025
- 보통 DB에 날짜를 저장하려면 ctime() 함수보다는 time()을 사용하는 것이 좋다고 합니다.
- 그 이유는 time.ctime() 함수가 현재 시간을 문자열 형태로 반환하기 때문입니다.
- 그러나 반환 타입이 문자열이라 슬라이싱이 가능해 연도나, 시간, 요일 등을 쉽게 구할 수는 있습니다.
💡 time.sleep(secs)
- 주어진 seconds 동안 실행을 일시 중지해주는 함수입니다.
- 일정한 시간이 경과한 후에 실행되는 코드를 작성할 때 용이하고, 데이터 엔지니어링에 있어서는 중요한 함수입니다.
- 예를 들어, 데이터를 가져올 때의 로딩, 다량의 센서 데이터 처리, 블랙박스 영상 분석에 있어서 자주 사용되고,
- 하루에 한 번씩 크롤링을 하는 등의 주기성을 띠는 작업에도 활용할 수 있습니다.
✨ OS(운영체제) 모듈
- 로컬 데이터를 건드리거나, 데이터 시각화를 진행할 때 주로 이용되는 모듈입니다.
💡 os.getcwd()
- 현재 경로를 얻어낼 수 있는 함수입니다.
💡 os.listdir(path='.')
- 지정한 경로에 어떤 파일과 폴더가 있는지 리스트로 반환해주는 함수입니다.
- path를 지정하지 않는 경우에는 현재 경로를 기준으로 반환해줍니다!
✨ 모듈을 import하는 네 가지 방법
- import os
- from os import listdir
- 모듈 내에서 특정 함수(여기서는 listdir)만을 가져오고 싶을 때 사용하는 방법입니다.
- from os import *
- 모듈 내에 있는 모든 것들을 가져오고 싶을 때 사용하는 방법입니다.
- import os as winos
- 모듈명이 길어서 작성하기 힘들 때, as 키워드를 이용해 모듈명을 임시로 변경할 수 있습니다.
🧑🏻🍳 함수는 레시피, 모듈은 요리책
- 비유하자면, 함수는 하나의 작업을 수행하는 "조리법"이라고 생각하면 쉽습니다.
- 예를 들어 계란 프라이를 만드는 방법(조리법)을 정해 놓게 되면, 그 방법을 새로 설명하거나 정의하지 않아도 됩니다. (중복 코드 방지)
- 또한, 모듈은 여러 개의 함수(조리법)를 하나의 파일에 정리한 "요리책"과 같습니다.
- 여러 가지 조리법(함수)을 만들어 놓고, 이 조리법들을 하나의 요리책에 모아두어 언제든 불러와서 사용할 수 있게 됩니다.
👨🏻🏫 클래스
- 클래스는 다른 프로그래밍 언어에서도 제공되는 객체 지향 프로그래밍을 할 수 있게끔 도와주는 친구입니다.
- 대표적인 객체 지향 언어는 C++, Java, C#입니다.
✨ 클래스의 구조
- 클래스 선언부에는 class 키워드, 그리고 함수와 같이 키워드 다음에는 클래스명을 명시해줍니다.
- 클래스명은 암묵적으로 첫 글자를 대문자로 지정해줍니다.
- 클래스가 객체로 생성되는 과정을 인스턴스화라고 합니다.
💡 함수 선언
- 내부에는 함수를 선언할 수 있는데,
- 이때, 첫 번째 매개변수는 무조건 self로 지정해야 합니다.
def 함수명(self, 매개변수1, 매개변수2, ...):
self.변수명1 = 매개변수1
self.변수명2 = 매개변수2
...
- 위와 같이 'self.변수명1 = 매개변수1'을 통해 입력받은 값을 인스턴스의 속성으로 저장해주어야 합니다.
- 여기서 self를 사용하지 않으면, 변수는 함수 내부에서만 존재하고 인스턴스에는 저장되지 않습니다.
💡 생성자 선언
- 생성자와 소멸자도 선언이 가능합니다.
- 객체를 생성할 때 매개변수도 같이 초기화하고 싶을 때 보통 생성자를 선언하고,
- 생성자는 def __init__(self, …)로 초기화하게 됩니다. 특정 객체가 생성될 때에 자동으로 호출됩니다.
- 인스턴스 생성 시 클래스가 원하는 매개변수의 수를 전달해주지 않으면 TypeError: Class.init() missing x required positional arguments의 오류가 발생합니다.
- 이외에도 소멸자는 객체가 소멸될 때 자동 호출됩니다.
💡 변수 선언
- 마지막으로 변수도 선언이 가능합니다.
- 클래스 내부에서의 변수이기 때문에 객체 모두가 공유할 수 있는 변수입니다.
- 이 변수를 클래스 변수라고 하는데, 이 변수는 객체 없이 클래스명을 통해 바로 사용이 가능합니다.
✨ 클래스 실제 작성
- 실제로 연락처를 입력하고, 출력하고, 삭제하여 생성된 연락처 DB를 txt 파일로 저장하는 프로그램을 구현해 보았습니다.
# -*- coding: utf-8 -*-
"""
Created on Tue Feb 4 15:54:46 2025
@author: author
연락처를 입력, 출력, 삭제하는 프로그램 구현
종료 후에는 txt 파일로 저장
"""
# 연락처 클래스
class Contact:
# 연락처 클래스 생성자
def __init__(self, name, phone_number, email, addr):
self.name = name
self.phone_number = phone_number
self.email = email
self.addr = addr
# 인스턴스 정보 출력
def print_info(self):
print('==============================')
print('\t', '이름:', self.name)
print('\t', '번호:', self.phone_number)
print('\t', '메일:', self.email)
print('\t', '주소:', self.addr)
print('==============================')
# 메뉴 출력 함수
def print_menu():
print('==================================')
print('1. 연락처 입력')
print('2. 연락처 출력')
print('3. 연락처 삭제')
print('4. 종료')
menu = input('위 메뉴 중 하나를 선택해주세요: ')
return int(menu)
# 연락처 입력 함수
def set_contact():
name = input('이름을 입력하세요: ')
phone_number = input('번호를 입력하세요: ')
email = input('메일을 입력하세요: ')
addr = input('주소를 입력하세요: ')
contact = Contact(name, phone_number, email, addr)
return contact
# 연락처 정보를 출력하는 함수
def print_contact(contacts):
for contact in contacts:
contact.print_info()
# 이름만 출력하는 함수
def print_name(contacts):
for contact in contacts:
print(contact.name, end=', ')
# 이름을 받아 연락처를 삭제하는 함수
def delete_contact(contacts, name):
for i, contact in enumerate(contacts):
if contact.name == name:
del contacts[i]
# 연락처 정보 전체를 저장하는 함수
def store_contact(contacts):
f = open('db.txt', 'wt')
for contact in contacts:
f.write(contact.name + '\n')
f.write(contact.phone_number + '\n')
f.write(contact.email + '\n')
f.write(contact.addr + '\n')
f.close()
# 프로그램 실행 시 db.txt 자동 로딩하게 하는 함수
def load_contact(contacts):
f = open('db.txt', 'rt')
lines = f.readlines()
num = len(lines) / 4
num = int(num)
for i in range(num):
name = lines[4*i].rstrip('\n')
phone_number = lines[4*i+1].rstrip('\n')
email = lines[4*i+2].rstrip('\n')
addr = lines[4*i+3].rstrip('\n')
contact = Contact(name, phone_number, email, addr)
contacts.append(contact)
f.close()
# 실행 함수
def run():
contacts = []
load_contact(contacts)
while True:
menu = print_menu()
if menu == 1:
contacts.append(set_contact())
print('연락처가 저장되었습니다.')
elif menu == 2:
print_contact(contacts)
print('연락처가 모두 출력되었습니다.')
elif menu == 3:
print('현재 저장되어 있는 이름들은 다음과 같습니다.')
print_name(contacts)
print()
name = input('이 중 삭제하고 싶은 이름을 입력해주세요: ')
delete_contact(contacts, name)
print('해당 연락처가 삭제되었습니다.')
elif menu == 4:
break
else:
print('잘못된 메뉴입니다. 다시 선택해주세요.')
store_contact(contacts)
# 메인 함수
if __name__ == '__main__':
run()
🎭 클래스는 연극 대본!
- 보통 클래스를 붕어빵 틀로 비유하곤 하는데, 저는 이와 조금 다르게 '연극 대본'으로 비유하겠습니다.
- 연극 대본은 배우(인스턴스)가 어떻게 행동하고 대사해야 하는지(메서드)가 정의되어 있습니다.
- 또한, 같은 대본(클래스)을 가지고서 여러 배우(인스턴스)가 연기할 수 있습니다.
- 그러나 배우(인스턴스)마다 연기 스타일이나 특성(속성)이 다를 수가 있습니다.
🤔 6일차 회고
- 오늘은 함수, 모듈, 더 나아가 클래스의 이론과 실습을 진행했습니다. 이미 아는 내용이기에 따라가는데 어려움은 없었지만, 어제에 비해 급상승한 난이도 덕에 조금씩 흥미를 가지며 정리를 하고 있습니다.
- 후반부에 진행했던 클래스 구현 코드의 구조는 추후 불용어 사전을 구축할 때에도 쓰인다고 합니다.
- 전에 진행했던 프로젝트에서의 불용어 사전은 매번 외부에서 가져오거나 불용어 몇 개 추가하는 정도가 다였는데, 이 구조를 잘 가져가 추후 진행될 사전 구축에서 빛을 발하길 기대해봅니다...! ✨
- 내일은 Pandas 라이브러리를 이용해서 본격적인 데이터 분석을 진행할 예정입니다!
728x90
LIST
'부트캠프 > LG U+' 카테고리의 다른 글
🤔 Matplotlib을 활용한 본격적인 시각화 (2) | 2025.02.06 |
---|---|
🤔 Series와 DataFrame 그리고 Pandas (0) | 2025.02.06 |
🤔 Python Programming Basics (w. Spyder) (1) | 2025.02.03 |
🤔 Jupyter, folium 그리고 tkinter (2) | 2025.01.24 |
🤔 Python과 데이터 분석의 기초 (3) | 2025.01.23 |