TIL/[TIL]

[TIL]Python OOP, 모듈, 파일 입출력, 예외 처리와 NumPy 입문

namerong 2026. 7. 15. 16:05

이번 학습에서는 Python의 표준 API와 객체지향 문법, 모듈 사용, 파일 입출력, 예외 처리, NumPy 기초를 정리했다.
이전까지는 자료형과 함수 중심이었다면, 이번에는 Python으로 실제 프로그램 구조를 만드는 데 필요한 내용이 많았다.

1. datetime

datetime은 날짜와 시간을 다루는 표준 모듈이다.

현재 날짜와 시간을 가져올 때는 datetime.today() 또는 datetime.now()를 사용할 수 있다.

from datetime import datetime

now = datetime.now()
print(now)
print(now.date())
print(now.time())

날짜를 문자열로 바꿀 때는 strftime()을 사용한다.

now.strftime("%Y-%m-%d %H:%M:%S")

반대로 문자열을 날짜 객체로 바꿀 때는 strptime()을 사용한다.

text = "26-07-15 09:31:38"
parsed_date = datetime.strptime(text, "%y-%m-%d %H:%M:%S")

날짜 계산은 timedelta를 사용한다.

from datetime import timedelta

future_date = now + timedelta(days=5, hours=1)
past_date = now - timedelta(days=5)

날짜끼리 빼면 두 날짜 사이의 차이도 구할 수 있다.

from datetime import date

today = date.today()
target_date = date(2026, 12, 24)

diff = target_date - today

2. 객체지향과 클래스

Python에서도 클래스를 사용해 객체를 만들 수 있다.

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def hello(self, greeting="안녕"):
        print(f"{greeting}, 나는 {self.age}살 {self.name}이야")

__init__()은 객체가 생성될 때 실행되는 초기화 메서드다.
Java의 생성자와 비슷한 역할을 한다.

Python 클래스 메서드의 첫 번째 매개변수로는 보통 self를 사용한다.

self.name = name
self.age = age

self는 현재 객체 자신을 의미한다.
Java의 this와 비슷하다고 보면 된다.


3. 클래스 메서드

인스턴스 메서드는 객체를 만든 뒤 객체 기준으로 호출한다.

person = Person("홍길동", 20)
person.hello()

반면 클래스 메서드는 클래스 자체와 관련된 동작을 만들 때 사용한다.

class SongpaStudent:
    @classmethod
    def create(cls):
        ...

@classmethod가 붙으면 첫 번째 매개변수로 인스턴스가 아니라 클래스 자체가 전달된다.
이때 관례적으로 cls라는 이름을 사용한다.


4. 캡슐화

캡슐화는 객체의 내부 데이터를 외부에서 직접 수정하지 못하게 하고, 정해진 메서드를 통해서만 다루게 만드는 방식이다.

Python에서는 속성 이름 앞에 __를 붙이면 외부에서 직접 접근하기 어렵게 만들 수 있다.

class Account:
    def __init__(self, name, balance):
        self.__name = name
        self.__balance = balance

잔액처럼 함부로 바뀌면 안 되는 값은 직접 수정하지 못하게 하고, 입금/출금 메서드를 통해서만 변경하는 것이 좋다.

def deposit(self, money):
    if money > 0:
        self.__balance += money

이렇게 하면 객체 내부 상태를 더 안전하게 관리할 수 있다.


5. Getter, Setter와 property

private 속성은 외부에서 직접 접근하기 어렵기 때문에 값을 읽거나 수정하는 통로가 필요하다.

Python에서는 @property를 사용하면 메서드를 속성처럼 사용할 수 있다.

class User:
    def __init__(self, name, point):
        self.__name = name
        self.__point = point

    @property
    def point(self):
        return self.__point

    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, name):
        self.__name = name

이렇게 하면 user.name처럼 속성처럼 읽고 쓸 수 있지만, 내부적으로는 메서드를 거치게 된다.
Java의 getter/setter와 비슷한 역할이다.


6. Scope

Scope는 변수가 유효한 범위를 의미한다.

구분 의미
global scope 전역 범위, 어디서나 접근 가능
local scope 함수나 블록 내부 범위, 밖에서는 접근 불가

함수 안에서 만든 변수는 기본적으로 함수 밖에서 사용할 수 없다.

def test():
    x = 10

# print(x)  # 함수 밖에서는 접근 불가

전역 변수를 함수 안에서 수정하려면 global을 사용할 수 있다.
다만 전역 상태를 많이 수정하면 코드 흐름이 복잡해지기 때문에 꼭 필요한 경우에만 쓰는 것이 좋다.


7. Module

모듈은 Python 코드가 들어 있는 .py 파일이다.
다른 파일에서 import해서 재사용할 수 있다.

예를 들어 my_math.py에 다음 코드가 있을 수 있다.

x: int = 100
pi: float = 3.14

def get_circle_area(r: int):
    return r ** 2 * pi

다른 파일에서는 이렇게 가져와 사용할 수 있다.

from songpawork import my_math

my_math.get_circle_area(10)

또는 별칭을 붙일 수 있다.

from songpawork import my_math as m

m.get_circle_area(10)

특정 값만 가져올 수도 있다.

from songpawork.my_math import x, pi, get_circle_area

하지만 from module import * 방식은 어떤 이름이 들어오는지 명확하지 않아서 권장되지 않는다.


8. __name__ == "__main__"

모듈 파일에서 자주 보이는 구문이다.

if __name__ == "__main__":
    print("직접 실행할 때만 실행")

이 코드는 해당 파일을 직접 실행할 때만 동작한다.
다른 파일에서 import할 때는 실행되지 않는다.

즉, 모듈 안에 테스트용 실행 코드를 넣고 싶을 때 유용하다.


9. os 모듈

os 모듈은 운영체제와 관련된 기능을 제공한다.

자주 쓰는 기능은 다음과 같다.

기능 설명
os.getcwd() 현재 작업 디렉토리 확인
os.listdir() 디렉토리 목록 확인
os.mkdir() 디렉토리 생성
os.path.exists() 경로 존재 여부 확인
os.path.isfile() 파일 여부 확인
os.path.join() 경로 조합

경로를 직접 문자열로 이어 붙이는 것보다 os.path.join()을 쓰는 것이 좋다.

file_path = os.path.join("test", "helloworld.txt")

운영체제마다 경로 구분자가 다를 수 있기 때문에, 경로 조합은 모듈에 맡기는 편이 안전하다.


10. 파일 입출력

Python에서 파일을 읽고 쓸 때는 open()을 사용한다.

f = open("sample.txt", "w", encoding="utf-8")
f.write("Hello Python")
f.close()

하지만 파일은 열었으면 반드시 닫아야 하므로, 보통 with문을 많이 사용한다.

with open("sample.txt", "w", encoding="utf-8") as f:
    f.write("Hello Python")

with를 사용하면 블록이 끝날 때 파일이 자동으로 닫힌다.

파일 읽기는 다음처럼 할 수 있다.

with open("sample.txt", "r", encoding="utf-8") as f:
    print(f.read())

읽기 방식은 여러 가지가 있다.

메서드 설명
read() 전체 내용 읽기
readline() 한 줄씩 읽기
readlines() 모든 줄을 리스트로 읽기
write() 문자열 쓰기
writelines() 여러 줄 쓰기

파일 모드도 중요하다.

모드 의미
r 읽기
w 쓰기, 기존 내용 덮어쓰기
a 추가 쓰기

11. 예외 처리

예외는 프로그램 실행 중 발생할 수 있는 오류 상황이다.
Python에서는 이름에 Error가 붙어도 대부분 Exception 계층의 하위 클래스로 다룬다.

기본 구조는 다음과 같다.

try:
    실행할 코드
except Exception as e:
    예외 발생 시 처리
else:
    예외가 없을 때 실행
finally:
    항상 실행

예외 종류별로 다르게 처리할 수도 있다.

try:
    ...
except ZeroDivisionError as e:
    ...
except IndexError as e:
    ...
except Exception as e:
    ...

finally는 예외가 발생하든 안 하든 실행된다.
파일 닫기, 연결 해제 같은 정리 작업에 자주 사용된다.

직접 예외를 발생시킬 수도 있다.

raise NotImplementedError("서비스 준비중입니다.")

아직 구현하지 않은 기능이나 의도적으로 실행을 막아야 하는 상황에서 사용할 수 있다.


12. NumPy 입문

NumPy는 숫자 계산과 배열 처리를 빠르게 하기 위한 Python 라이브러리다.

import numpy as np

Python list와 NumPy 배열은 + 연산 결과가 다르다.

a_list = [1, 2, 3]
b_list = [4, 5, 6]

print(a_list + b_list)  # [1, 2, 3, 4, 5, 6]

list의 +는 연결이다.

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])

print(a + b)  # [5 7 9]

NumPy 배열의 +는 요소별 계산이다.


13. NumPy 배열 생성

NumPy 배열은 여러 방식으로 만들 수 있다.

np.array([1, 2, 3])
np.zeros(5)
np.ones(5)
np.full((3, 4), 100)
np.arange(0, 10, 2)
np.linspace(0, 1, 5)
함수 의미
np.array() 리스트를 배열로 변환
np.zeros() 0으로 채운 배열 생성
np.ones() 1로 채운 배열 생성
np.full() 원하는 값으로 채운 배열 생성
np.arange() 일정 간격 기준으로 생성
np.linspace() 일정 개수로 균등 분할

arange와 linspace의 차이가 중요하다.

np.arange(0, 10, 2)      # 간격 기준
np.linspace(0, 10, 6)    # 개수 기준

14. NumPy 배열 속성

NumPy 배열은 모양, 차원, 요소 개수, 자료형을 확인할 수 있다.

arr = np.array([[80, 90, 100], [70, 88, 99]])

arr.shape
arr.ndim
arr.size
arr.dtype
속성 의미
shape 배열 모양
ndim 배열 차원 수
size 전체 요소 개수
dtype 요소 자료형

예를 들어 2행 3열 배열의 shape는 (2, 3)이다.

np.array([[80, 90, 100], [70, 88, 99]]).shape

NumPy 배열은 하나의 배열 안에서 하나의 자료형을 기준으로 맞추려 한다.
숫자와 문자열을 섞으면 전체가 문자열로 변환될 수 있다.

data = np.array([100, 200, "Python"])
print(data.dtype)

15. 핵심 정리

  1. datetime은 날짜/시간 조회, 포맷팅, 문자열 파싱, 날짜 계산에 사용한다.
  2. Python 클래스에서는 __init__()으로 객체 초기값을 설정한다.
  3. self는 현재 객체 자신을 의미한다.
  4. 캡슐화는 내부 속성을 직접 수정하지 못하게 하고 메서드로 제어하는 방식이다.
  5. @property를 사용하면 getter/setter를 속성처럼 사용할 수 있다.
  6. scope는 변수가 유효한 범위이며, 전역과 지역 범위가 구분된다.
  7. 모듈은 재사용 가능한 .py 파일이며 import로 가져와 사용한다.
  8. __name__ == "__main__"은 직접 실행할 때만 동작하는 코드를 구분할 때 사용한다.
  9. os 모듈은 경로, 디렉토리, 파일 존재 여부 확인에 사용한다.
  10. 파일 입출력은 with open() 방식이 안전하다.
  11. 예외 처리는 try-except-else-finally 구조로 정상 흐름을 복구하는 데 사용한다.
  12. NumPy 배열은 list와 달리 요소별 연산이 가능하다.
  13. NumPy는 배열 생성 함수와 shape, ndim, size, dtype 같은 속성을 자주 사용한다.