클래스 (Class)
클래스는 데이터(속성)와 기능(메서드)을 하나로 묶는 틀입니다.
관련 있는 데이터와 함수를 하나의 단위로 구조화할 때 사용합니다.
클래스 정의와 인스턴스 생성
class Sample:
def __init__(self, sample_id, species, coverage):
self.sample_id = sample_id # 인스턴스 속성
self.species = species
self.coverage = coverage
def describe(self):
print(f"{self.sample_id} | {self.species} | {self.coverage}x")
def is_high_coverage(self, threshold=30.0):
return self.coverage >= threshold
# 인스턴스 생성
s1 = Sample("sample_01", "Homo sapiens", 30.5)
s2 = Sample("sample_02", "Mus musculus", 18.2)
s1.describe() # sample_01 | Homo sapiens | 30.5x
print(s1.is_high_coverage()) # True
print(s2.is_high_coverage()) # False
print(s1.sample_id) # sample_01
__init__은 인스턴스가 생성될 때 자동으로 호출되는 초기화 메서드입니다. self는 인스턴스 자신을 가리키며, 메서드의 첫 번째 인자로 항상 포함됩니다.
클래스 변수와 인스턴스 변수
class Sample:
species_db = [] # 클래스 변수: 모든 인스턴스가 공유
def __init__(self, sample_id, species):
self.sample_id = sample_id # 인스턴스 변수: 각 인스턴스마다 독립
self.species = species
Sample.species_db.append(species)
s1 = Sample("sample_01", "Homo sapiens")
s2 = Sample("sample_02", "Mus musculus")
print(Sample.species_db) # ['Homo sapiens', 'Mus musculus']
특수 메서드 (dunder method)
__로 시작하고 끝나는 메서드로, 파이썬 내장 동작을 정의합니다.
class Sample:
def __init__(self, sample_id, coverage):
self.sample_id = sample_id
self.coverage = coverage
def __repr__(self):
return f"Sample(id={self.sample_id}, coverage={self.coverage})"
def __str__(self):
return f"{self.sample_id} ({self.coverage}x)"
def __len__(self):
return int(self.coverage)
def __lt__(self, other):
return self.coverage < other.coverage
s = Sample("sample_01", 30.5)
print(repr(s)) # Sample(id=sample_01, coverage=30.5)
print(str(s)) # sample_01 (30.5x)
print(len(s)) # 30
samples = [Sample("s1", 30.5), Sample("s2", 18.2), Sample("s3", 45.8)]
samples.sort() # __lt__ 덕분에 coverage 기준으로 정렬 가능
__repr__은 객체의 공식 표현(디버깅용), __str__은 사람이 읽기 좋은 표현입니다. print()는 __str__을 사용하고, 없으면 __repr__을 사용합니다.
상속
기존 클래스의 속성과 메서드를 물려받아 새 클래스를 만듭니다.
class SequenceSample(Sample):
def __init__(self, sample_id, species, coverage, seq_length):
super().__init__(sample_id, species, coverage) # 부모 클래스 초기화
self.seq_length = seq_length
def describe(self):
super().describe() # 부모 메서드 호출
print(f" Sequence length: {self.seq_length}bp")
def get_gc_per_mb(self, gc_count):
return gc_count / (self.seq_length / 1_000_000)
s = SequenceSample("sample_01", "Homo sapiens", 30.5, 3_000_000_000)
s.describe()
print(isinstance(s, Sample)) # True
print(isinstance(s, SequenceSample)) # True
모듈 (Module)
모듈은 파이썬 코드를 담은 .py 파일입니다. 함수, 클래스, 변수를 다른 파일에서 재사용할 수 있도록 분리합니다.
모듈 임포트
# 모듈 전체 임포트
import math
print(math.sqrt(144))
# 특정 이름만 임포트
from math import sqrt, pi
print(sqrt(144))
# 별칭 사용
import numpy as np
import pandas as pd
from collections import defaultdict as dd
직접 만든 모듈 사용
utils.py 파일을 작성하고 다른 파일에서 임포트할 수 있습니다.
# utils.py
def calc_gc(seq):
return (seq.count("G") + seq.count("C")) / len(seq)
def reverse_complement(seq):
complement = {"A": "T", "T": "A", "G": "C", "C": "G"}
return "".join(complement[b] for b in reversed(seq))
GC_THRESHOLD = 0.5
# main.py
import utils
seq = "ATCGATCGGGCC"
print(utils.calc_gc(seq))
print(utils.reverse_complement(seq))
print(utils.GC_THRESHOLD)
# 또는
from utils import calc_gc, reverse_complement
print(calc_gc(seq))
if __name__ == "__main__"
모듈을 직접 실행할 때와 임포트할 때의 동작을 구분합니다.
# utils.py
def calc_gc(seq):
return (seq.count("G") + seq.count("C")) / len(seq)
if __name__ == "__main__":
# 이 블록은 utils.py를 직접 실행할 때만 동작
# 다른 파일에서 import할 때는 실행되지 않음
test_seq = "ATCGATCGGGCC"
print(f"GC: {calc_gc(test_seq):.2%}")
패키지
여러 모듈을 디렉토리로 묶은 것을 패키지라고 합니다. 디렉토리 안에 __init__.py 파일이 있으면 패키지로 인식됩니다.
biotools/
__init__.py
sequence.py
alignment.py
utils.py
from biotools import sequence
from biotools.utils import calc_gc
예외처리 (Exception Handling)
프로그램 실행 중 오류가 발생해도 종료되지 않고 적절히 처리할 수 있도록 하는 구조입니다.
try / except
try:
result = 10 / 0
except ZeroDivisionError:
print("0으로 나눌 수 없습니다.")
# 여러 예외 처리
try:
with open("data.csv", "r") as f:
content = f.read()
value = int(content)
except FileNotFoundError:
print("파일을 찾을 수 없습니다.")
except ValueError:
print("정수로 변환할 수 없습니다.")
자주 발생하는 예외
| 예외 | 발생 상황 |
| ValueError | 올바르지 않은 값 (예: int("abc")) |
| TypeError | 잘못된 타입 (예: "a" + 1) |
| KeyError | 딕셔너리에 없는 키 접근 |
| IndexError | 리스트 범위를 벗어난 인덱스 |
| FileNotFoundError | 파일이 존재하지 않음 |
| PermissionError | 파일 접근 권한 없음 |
| ZeroDivisionError | 0으로 나누기 |
| AttributeError | 없는 속성 접근 |
| ImportError | 모듈 임포트 실패 |
except as
예외 객체를 변수로 받아 오류 내용을 확인합니다.
try:
with open("data.csv", "r") as f:
content = f.read()
except FileNotFoundError as e:
print(f"오류 발생: {e}")
# 오류 발생: [Errno 2] No such file or directory: 'data.csv'
else와 finally
try:
value = int(input("숫자 입력: "))
except ValueError:
print("숫자가 아닙니다.")
else:
# 예외가 발생하지 않았을 때 실행
print(f"입력값: {value}")
finally:
# 예외 발생 여부에 관계없이 항상 실행
print("처리 완료")
finally는 파일이나 네트워크 연결처럼 반드시 정리가 필요한 리소스를 처리할 때 유용합니다. 다만 파일의 경우 with 문을 사용하면 finally를 별도로 작성하지 않아도 됩니다.
예외 발생시키기: raise
의도적으로 예외를 발생시킵니다. 함수 입력값 검증 시 자주 사용합니다.
def calc_gc(seq):
if not seq:
raise ValueError("시퀀스가 비어있습니다.")
if not all(b in "ATCG" for b in seq.upper()):
raise ValueError(f"유효하지 않은 염기가 포함되어 있습니다: {seq}")
return (seq.count("G") + seq.count("C")) / len(seq)
try:
gc = calc_gc("ATCGXXXX")
except ValueError as e:
print(f"입력 오류: {e}")
사용자 정의 예외
내장 예외를 상속해서 도메인에 맞는 예외를 만들 수 있습니다.
class SequenceError(Exception):
pass
class InvalidBaseError(SequenceError):
def __init__(self, base, position):
self.base = base
self.position = position
super().__init__(f"위치 {position}에 유효하지 않은 염기: {base}")
def validate_sequence(seq):
valid_bases = set("ATCG")
for i, base in enumerate(seq.upper()):
if base not in valid_bases:
raise InvalidBaseError(base, i)
try:
validate_sequence("ATCGXATCG")
except InvalidBaseError as e:
print(e) # 위치 4에 유효하지 않은 염기: X
예외처리 주의사항
너무 광범위한 예외를 잡으면 예상치 못한 오류를 숨길 수 있습니다.
# 좋지 않은 예: 모든 예외를 무시
try:
process_data()
except Exception:
pass
# 권장: 예상하는 예외만 처리
try:
process_data()
except FileNotFoundError:
print("입력 파일이 없습니다.")
except ValueError as e:
print(f"데이터 형식 오류: {e}")
정리표
| 항목 | 핵심 내용 |
| __init__ | 인스턴스 초기화 메서드 |
| self | 인스턴스 자신을 가리키는 참조 |
| super() | 부모 클래스 메서드 호출 |
| __repr__ / __str__ | 객체 문자열 표현 정의 |
| import | 모듈 전체 임포트 |
| from ... import | 특정 이름만 임포트 |
| if __name__ == "__main__" | 직접 실행 시에만 동작하는 블록 |
| try / except | 예외 처리 |
| else | 예외 없을 때 실행 |
| finally | 항상 실행 |
| raise | 예외 발생 |
'BI&Programming-Tools > Python' 카테고리의 다른 글
| [파이썬 기초] Matplotlib / Seaborn 시각화 (0) | 2026.06.18 |
|---|---|
| [파이썬 기초] NumPy & Pandas 기초 (0) | 2026.06.18 |
| [파이썬 기초] 파일 형식 처리 (CSV, TSV, FASTA) (0) | 2026.06.17 |
| [파이썬 기초] 변수 범위와 파일 읽기·쓰기 (0) | 2026.06.17 |
| [파이썬 기초] 정규표현식 (re 모듈) (0) | 2026.06.17 |
