728x90

Flask-Migrate는 db와 sqlalchemy models.py의 차이를 추적하여 업그레이드/다운그레이드 스크립트 자동으로 생성해줌

 

Flask-Migrate 소개 및 기초 사용법

Flask-Migrate란? Flask-Migrate는 SQLAlchemy를 사용하는 Flask 애플리케이션에서 데이터베이스 스키마를 효과적으로 관리하기 위한 extension Flask-Migrate는 Alembic이라는 데이터베이스 마이그레이션 툴을 내부

bigseok.tistory.com

 

만약에 서비스에 필요한 DB table 초기 데이터도 함께 관리하고 싶다면 마이그레이션 스크립트에 수동으로  추가해주어야 함

 


1. DB 초기화

flask db init

위의 명령어를 수행한 위치에 migrations 폴더 자동으로 생성됨

2. 마이그레이션 스크립트 생성

flask db migrate -m "Initial migration."

migrations/versions 폴더 하위에 {revision}_{message}.py 스크립트가 자동으로 생성됨

3. 마이그레이션 스크립트에 수동으로 초기데이터 변경내용 추가

마이그레이션 스크립트 업그레이드 함수에 초기데이터삽입 코드 추가예시

# /migrations/versions/{revision}_{message}.py
def upgrade():
    ...생략...
    # ### end Alembic commands ###
    add_initial_data()

def add_initial_data():
    op.bulk_insert(
        sa.table('tb_users',
            sa.column('name'),
            sa.column('user_id'),
            sa.column('password'),
            sa.column('admin_yn'),
            sa.column('email')
        ),
        [
            {
                'name': '관리자',
                'user_id': 'admin',
                'password': 'admin123!@#',
                'admin_yn': 'Y',
                'email': 'admin@test.com'
            }
        ]
    )

 

  • alembic op모듈 주요 기능
    1. 테이블 작업
      • op.create_table(): 새로운 테이블을 생성
      • op.drop_table(): 기존 테이블을 삭제
      • op.add_column(): 기존 테이블에 새로운 열을 추가
      • op.drop_column(): 기존 테이블에서 열을 삭제
      • op.alter_column(): 열의 속성을 변경
    2. 인덱스 작업
      • op.create_index(): 새로운 인덱스를 생성
      • op.drop_index(): 기존 인덱스를 삭제
    3. 데이터 작업
      • op.execute(): SQL 문을 직접 실행
    4. 제약 조건 작업
      • op.create_foreign_key(): 새로운 외래 키 제약 조건을 생성
      • op.create_primary_key(): 새로운 기본 키 제약 조건을 생성
      • op.create_check_constraint(): 새로운 체크 제약 조건을 생성
    5. 기타 작업
      • op.rename_table(): 기존 테이블의 이름을 변경
      • op.rename_column(): 기존 열의 이름을 변경
      • op.create_sequence(): 새로운 데이터베이스 시퀀스를 생성
    6. 대량 데이터 작업
      • op.bulk_insert(): 테이블에 대량 삽입을 수행
      • op.bulk_update(): 테이블에서 대량 업데이트를 수행
728x90
728x90

Flask-Migrate란?

Flask-Migrate는 SQLAlchemy를 사용하는 Flask 애플리케이션에서 데이터베이스 스키마를 효과적으로 관리하기 위한 extension

Flask-Migrate는 Alembic이라는 데이터베이스 마이그레이션 툴을 내부적으로 사용

Flask 애플리케이션과의 원활한 통합을 제공하여 데이터베이스 마이그레이션을 더욱 편리하게 관리 가능

https://flask-migrate.readthedocs.io/en/latest/#why-use-flask-migrate-vs-alembic-directly

Flask-Migrate 사용법

설치

pip install Flask-Migrate

 

환경변수 설정

flask app 실행파일명이 app.py나 wsgi.py가 아닌 이상 환경변수(.env파일)에 flask app 실행파일명 설정 필수

FLASK_APP= "__run__.py"

 

마이그레이션 (alembic) 초기화

flask db init

 

마이그레이션 스크립트 생성

flask db migrate -m "Initial migration."

현재의 SQLAlchemy 모델과 데이터베이스 상태를 비교하여 마이그레이션 스크립트를 자동으로 생성

 

버전업 (DB에 스키마 변경사항 반영)

flask db upgrade [--sql] [--tag TAG] <revision>
# 데이터베이스를 업그레이드 revision주어지지 않으면 최신버전

 

버전 다운그레이드 (최초 버전으로)

flask db downgrade [--sql] [--tag TAG] <revision>
# 데이터베이스를 다운그레이드, revision이 주어지지 않으면 -1

 

 

728x90
728x90

일반적으로 pipenv를 이용하여 가상환경을 생성할 때, Pipfile이 이미 존재하는 경우 아래와 같이 가상환경을 구성함

pipenv install

 

 

하지만 로컬에 파이썬 여러버전이 깔려있는 경우 RuntimeError: Failed to lock Pipfile.lock! 에러가 발생하기도 함

그럴때는 아래와 같이 가상환경을 생성한 뒤, 가상환경 shell에 접속해서 pipenv를 설치한 후 pipenv install을 실행하면 됨

pipenv --python 버전
pipenv shell
pipenv install

 

 

 

728x90
728x90

alembic이란?

SQLAlchemy의 확장으로, 데이터베이스 스키마의 버전관리를 위한 도구

데이터베이스 마이그레이션, 스키마 버전관리, 백업 등의 기능을 제공

alembic의 주요 특징

  • 마이그레이션 지원 : 데이터베이스 스키마를 업데이트하거나 변경할 때 사용되는 마이그레이션 스크립트를 생성하고 관리
  • 버전관리 지원 : 각 마이그레이션은 버전으로 관리되며, 데이터베이스 스키마의 특정 버전으로 이동 가능
  • 다양한 데이터베이스 지원 : SQLAlchemy를 기반으로 하기 때문에 다양한 데이터베이스 엔진 지원
  • 명령행 도구 지원 : 명령행도구를 제공하여 터미널에서 간편하게 마이그레이션 수행 가능

alembic 설치

pip install alembic

alembic 기초 사용법

1. 초기 세팅

alembic init alembic

 

생성된 alembic.ini 파일을 열어 데이터베이스 연결 정보를 설정

# alembic.ini 예시
[alembic]
script_location = alembic 
sqlalchemy.url = driver://user:password@dbhost:dbport/dbname

# script_location : 마이그레이션 스크립트 위치
# model_location : models.py 위치, 설정된 디렉토리 내에 있는 모든 Python 파일을 모델로 인식

 

2. SQLAlchemy 모델 정의 (이미 정의된 모델이 있다면 pass)

# models.py 예시
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String)
    email = Column(String)

 

3. 마이그레이션 스크립트 생성

변경된 모델을 기반으로 마이그레이션 스크립트 자동으로 생성됨

alembic revision --autogenerate -m "message"

 

생성된 스크립트를 열어보면 Alembic이 모델의 변경사항을 감지하고 스키마를 업데이트하기 위한 SQL 명령어를 생성한 것을 확인할 수 있음

# 생성된 스크립트 예시 my_migration/versions/<timestamp>_message.py
from alembic import op
import sqlalchemy as sa

def upgrade():
    op.create_table('users',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('username', sa.String(), nullable=True),
        sa.Column('email', sa.String(), nullable=True),
        sa.PrimaryKeyConstraint('id')
    )

def downgrade():
    op.drop_table('users')

 

4. 마이그레이션 적용

# 최신버전으로 업그레이드
alembic upgrade head

# 특정 버전으로 업그레이드
alembic upgrade {revision_number}

# 최초 버전으로 다운그레이드
alembic downgrade base

# 특정버전으로 다운그레이드
alembic downgrade {revision_number}

참고

alembic 공식문서 튜토리얼

728x90
728x90

FastAPI 개발자 tiangolo는 FastAPI를 어떻게 사용할까 궁금해서 찾아본 프로젝트

https://github.com/tiangolo/full-stack-fastapi-postgresql

이번 게시글에서는 프로젝트 설정파일인 project.toml을 분석하려고 함

 

pyproject.toml 설명

[tool.poetry]
name = "app"
version = "0.1.0"
description = ""
authors = ["Admin <admin@example.com>"]

[tool.poetry.dependencies]
python = "^3.10"
uvicorn = "^0.24.0.post1"
fastapi = "^0.104.1"
python-multipart = "^0.0.6"
email-validator = "^2.1.0.post1"
celery = "^5.3.5"
passlib = {extras = ["bcrypt"], version = "^1.7.4"}
tenacity = "^8.2.3"
pydantic = ">2.0"
emails = "^0.6"
gunicorn = "^21.2.0"
jinja2 = "^3.1.2"
alembic = "^1.12.1"
python-jose = {extras = ["cryptography"], version = "^3.3.0"}
httpx = "^0.25.1"
psycopg = {extras = ["binary"], version = "^3.1.13"}
sqlmodel = "^0.0.16"
# Pin bcrypt until passlib supports the latest
bcrypt = "4.0.1"
pydantic-settings = "^2.2.1"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.3"
pytest-cov = "^4.1.0"
mypy = "^1.8.0"
ruff = "^0.2.2"
pre-commit = "^3.6.2"

[tool.isort]
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
line_length = 88

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

[tool.mypy]
strict = true

[tool.ruff]
target-version = "py310"

[tool.ruff.lint]
select = [
    "E",  # pycodestyle errors
    "W",  # pycodestyle warnings
    "F",  # pyflakes
    "I",  # isort
    "B",  # flake8-bugbear
    "C4",  # flake8-comprehensions
    "UP",  # pyupgrade
]
ignore = [
    "E501",  # line too long, handled by black
    "B008",  # do not perform function calls in argument defaults
    "W191",  # indentation contains tabs
    "B904",  # Allow raising exceptions without from e, for HTTPException
]

[tool.ruff.lint.pyupgrade]
# Preserve types, even if a file imports `from __future__ import annotations`.
keep-runtime-typing = true

 

  • [tool.poetry] 섹션
    • 프로젝트의 기본 정보를 정의
    • name: 프로젝트의 이름
    • version: 프로젝트의 버전
    • description: 프로젝트에 대한 간단한 설명
    • authors: 프로젝트 저자들의 이메일 주소를 포함한 리스트
  • [tool.poetry.dependencies] 섹션
    • 여러 Python 라이브러리와 프레임워크에 대한 의존성을 정의 (requirements.txt와 유사한 역할)
    • python: 사용할 Python 버전
    • uvicorn, fastapi, python-multipart, ...: FastAPI와 관련된 라이브러리 및 도구들
    • pydantic: 데이터 유효성 검사 및 설정을 위한 라이브러리
    • gunicorn, jinja2, alembic, ...: 다양한 라이브러리 및 도구들
    • bcrypt: 비밀번호 해싱을 위한 라이브러리
    • pydantic-settings: Pydantic 설정을 관리하기 위한 도구
  • [tool.isort] 섹션
    • 코드를 정렬하기 위한 isort 설정
    • 참고 : isort는 Python 코드 파일의 import 문을 정렬해주는 도구
  • [build-system] 섹션
    • 프로젝트 빌드에 사용되는 도구 및 설정
  • [tool.mypy] 섹션
    • mypy 정적 타입 검사 도구의 설정
    • 참고 : mypy는 Python 코드의 정적 타입 검사를 수행하는 도구로 런타임 이전에 코드를 분석하여 타입 오류를 찾아내고 이를 사전에 방지
  • [tool.ruff] 섹션
    • ruff 코드 포맷터 및 정적 분석 도구의 설정
    • 참고 : ruff는 rust로 만든 매우 빠른 Python linter
    • 참고 : linter는 코드의 오류나 버그가 있는지 확인하고 정해진 규칙을 잘 지키고 있는지에 대한 것들을 개발하면서 확인 및 점검을 하기 위해 사용하는 도구

 

pyproject.toml을 이용한 poetry 가상환경 설정

pyproject.toml이 있는 경우 poetry를 이용하여 간단하게 가상환경을 세팅할 수 있음

pip install --upgrade pip
pip install poetry
poetry install
poetry shell

 

가상환경을 세팅한 후에는 vscode에서 F1Python: Select Interpreter 를 클릭하여 poetry 가상환경 사용 가능

 

참고 : FastAPI 개발자가 직접 개발한 FastAPI backend 시리즈

FastAPI 개발자가 직접 개발한 FastAPI backend 프로젝트 구조

FastAPI 개발자가 직접 개발한 FastAPI backend alembic

FastAPI 개발자가 직접 개발한 FastAPI backend DB 초기화 방법

FastAPI 개발자가 직접 개발한 FastAPI backend pyproject.toml

FastAPI 개발자가 직접 개발한 FastAPI backend 설정파일 config.py

FastAPI 개발자가 직접 개발한 FastAPI backend 데이터모델 models.py

 

728x90
728x90

FastAPI 개발자 tiangolo는 FastAPI를 어떻게 사용할까 궁금해서 찾아본 프로젝트

https://github.com/tiangolo/full-stack-fastapi-postgresql

 

FastAPI(백엔드)의 기본적인 프로젝트 구조는 아래와 같음

```

app
├── alembic # 데이터베이스 마이그레이션을 관리하는 Alembic 설정 파일 및 스크립트가 저장된 디렉토리
├── api # FastAPI 애플리케이션의 API 엔드포인트 및 라우터가 정의된 디렉토리
├── core # 애플리케이션의 핵심 기능 및 설정이 정의된 모듈이 위치하는 디렉토리
├── schemas # Pydantic 스키마 정의가 포함된 디렉토리로, 데이터의 유효성 검사와 API 요청 및 응답의 구조를 정의
├── email-templates # 이메일 템플릿 파일이 저장된 디렉토리
├── tests # 테스트 파일이 위치한 디렉토리
├── __init__.py # Python에서 패키지로 인식되도록 하는 빈 __init__.py 파일
├── backend_pre_start.py # FastAPI 애플리케이션 시작 전에 실행할 코드가 정의된 파일
├── celeryworker_pre_start.py # Celery worker 시작 전에 실행할 코드가 정의된 파일
├── initial_data.py # 애플리케이션 초기 데이터를 설정하는 스크립트 파일
├── tests_pre_start.py # 테스트 시작 전에 실행할 코드가 정의된 파일
├── main.py # FastAPI 애플리케이션의 진입점이 되는 파일로, API 라우터를 구성하고 애플리케이션을 실행
├── models.py # SQLAlchemy 모델이 정의된 파일
├── crud.py # 데이터베이스 CRUD(Create, Read, Update, Delete) 연산을 수행하는 함수가 정의된 파일
├── utils.py # 애플리케이션에서 사용되는 유틸리티 함수가 정의된 파일
└── worker.py # Celery worker의 작업을 정의하는 파일

pyproject.toml # Poetry 프로젝트의 설정 파일로, 의존성 및 프로젝트 메타데이터를 정의
.env # 환경 변수 설정이 담긴 파일
.dockerignore # Docker 이미지 빌드 시 제외할 파일 및 디렉토리를 지정하는 파일
.gitignore # Git으로 추적하지 않을 파일 및 디렉토리를 지정하는 파일
alembic.ini # Alembic의 설정 파일로, 데이터베이스 마이그레이션 설정을 정의 # 
backend.dockerfile # FastAPI 애플리케이션을 위한 Docker 이미지를 빌드하는 데 사용되는 Docker 파일
celeryworker.dockerfile # Celery worker를 위한 Docker 이미지를 빌드하는 데 사용되는 Docker 파일
prestart.sh # FastAPI 애플리케이션 시작 전에 실행할 스크립트 파일
tests-start.sh # 테스트 시작 시 실행할 스크립트 파일
worker-start.sh # Celery worker 시작 시 실행할 스크립트 파일

```

 

참고 : FastAPI 개발자가 직접 개발한 FastAPI backend 시리즈

FastAPI 개발자가 직접 개발한 FastAPI backend 프로젝트 구조

FastAPI 개발자가 직접 개발한 FastAPI backend alembic

FastAPI 개발자가 직접 개발한 FastAPI backend DB 초기화 방법

FastAPI 개발자가 직접 개발한 FastAPI backend pyproject.toml

FastAPI 개발자가 직접 개발한 FastAPI backend 설정파일 config.py

FastAPI 개발자가 직접 개발한 FastAPI backend 데이터모델 models.py

 

728x90
728x90

git fork 한 프로젝트에 pyproject.toml이 있는 경우 poetry를 이용하여 간단하게 가상환경을 세팅할 수 있음

pip install --upgrade pip
pip install poetry
poetry install
poetry shell

 

 

poetry 사용법

728x90

'Python' 카테고리의 다른 글

RuntimeError: Failed to lock Pipfile.lock!  (0) 2024.03.05
alembic 소개 및 기초 사용법  (0) 2024.03.05
pyproject.toml 이란?  (0) 2024.03.03
객체지향 설계 5원칙 (SOLID)  (0) 2024.03.02
파이썬 객체지향 프로그래밍  (0) 2024.03.02
728x90

pyproject.toml이란?

파이썬 프로젝트의 표준 파일로, PEP 518PEP 621에 따라 정의됨

pyproject.toml는 프로젝트의 메타데이터 및 빌드에 필요한 도구들의 설정을 포함하는 설정파일

pyproject.toml 등장 배경

setuptools는 파이썬 프로젝트를 패키징하는 라이브러리로 널리 사용되었음

setuptools는 설정파일로 setup.py를 사용하는데, setuptools에 종속적임

setuptools가 파이썬 표준 라이브러리가 아니고, 다른 여러 빌드 시스템이 존재하기 때문에 개선할 필요성이 있었음

 

이를 개선하기 위해 특정 빌드 시스템에 종속되지 않는 선언적인 설정 파일 pyproject.toml이 제안됨

setup.py 대신 pyproject.toml을 사용한다는 것은 setuptools라는 특정한 라이브러리에 파이썬 패키징 시스템이 종속되지 않게 된다는 것을 의미함

pyproject.toml의 빌드시스템 설정파일로 사용하는 방법

pyproject.toml은 TOML 포맷으로 만들어진 설정파일

파이썬 패키지를 어떻게 빌드하는지, 어떤 빌드 시스템을 사용해야 하는지를 명시

 

<setuptools를 빌드시스템으로 사용하는 pyproject.toml 예시>

# pyproject.toml 예시
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

 

<flit을 빌드시스템으로 사용하는 pyproject.toml 예시>

[build-system]
requires = ["flit_core"]
build-backend = "flit_core.buildapi"

pyproject.toml에 그 외 설정을 저장하는 방법

개발과 관련된 설정 값을 관리하는 용도로도 pyproject.toml을 사용할 수 있음

빌드 전에 수행되어야 하는 테스트, 코드 포맷팅 등에 대한 정보를 pyproject.toml에 함께 적으면 유용함

 

<코드 포맷팅 도구 black, 테스트용 프레임워크 pytest의 설정값을  pyproject.toml에 저장하는 예시>

# pyproject.toml of black
[tool.black]
line-length = 88
target-version = ['py37', 'py38', 'py39', 'py310']
include = '\.pyi?$'
exclude = '''
/(
  \.git
  | \.mypy_cache
  | \.venv
  | _build
  | build
  | dist
)/
'''

# pyproject.toml of pytest
[tool.pytest.ini_options]
minversion = "6.0"
addopts = "-ra -q"
testpaths = ["tests"]

참고

- 파이썬 패키징의 과거, 현재, 그리고 미래

728x90
728x90

SRP (Single Responsibility Principle) : 단일 책임 원칙

하나의 클래스는 하나의 책임만 가져야 함

## 단일 책임 원칙을 준수하지 않은 예시
class User:
    def __init__(self, username, email):
        self.username = username
        self.email = email

    def save_to_database(self):
        # 데이터베이스에 저장하는 작업

    def send_email(self, message):
        # 이메일 보내는 작업

 

## 단일책임원칙을 준수하도록 수정
class User:
    def __init__(self, username, email):
        self.username = username
        self.email = email

class UserRepository:
    def save_to_database(self, user):
        # 데이터베이스에 저장하는 작업

class EmailService:
    def send_email(self, user, message):
        # 이메일 보내는 작업

OCP (Open-Closed Principle) : 개방 폐쇄 원칙

소프트웨어의 구성 요소(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 함

## 개방/폐쇄 원칙을 위반한 예시
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

class AreaCalculator:
    def calculate_area(self, rectangle):
        return rectangle.width * rectangle.height

 

## 개방/폐쇄 원칙을 준수하도록 수정
# 추상 클래스를 이용한 확장 가능한 디자인
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

LSP (Liskov Substitution Principle) : 리스 코프 치환 원칙

자식클래스는 언제나 부모클래스를 대체할 수 있어야 함

## 리스코프 치환 원칙을 위반한 예시
class Bird:
    def fly(self):
        pass

class Penguin(Bird):
    def fly(self):
        raise Exception("Penguins can't fly!")

def make_bird_fly(bird):
    bird.fly()

 

## 리스코프 치환 원칙을 준수하도록 수정
# 추상 클래스를 사용하여 공통된 인터페이스 정의
from abc import ABC, abstractmethod

class Bird(ABC):
    @abstractmethod
    def fly(self):
        pass

class Sparrow(Bird):
    def fly(self):
        print("Sparrow is flying")

class Penguin(Bird):
    def fly(self):
        print("Penguin can't fly")

def make_bird_fly(bird):
    bird.fly()

ISP (Interface Segragation Principle) : 인터페이스 분리 원칙

클라이언트는 자신이 사용하지 않는 메서드에 의존해서는 안됨

## 인터페이스 분리 원칙을 위반한 예시
class Worker:
    def work(self):
        pass

    def eat(self):
        pass

class SuperWorker(Worker):
    def work(self):
        pass

    def eat(self):
        pass

 

## 인터페이스 분리 원칙을 준수하도록 수정
# 인터페이스를 분리하여 클라이언트가 필요한 메서드만 사용
class Workable(ABC):
    @abstractmethod
    def work(self):
        pass

class Eatable(ABC):
    @abstractmethod
    def eat(self):
        pass

class Worker(Workable, Eatable):
    def work(self):
        pass

    def eat(self):
        pass

class SuperWorker(Workable, Eatable):
    def work(self):
        pass

    def eat(self):
        pass

DIP (Dependency Inversion Principle) : 의존 관계 역전 원칙

고수준 모듈은 저수준 모듈에 의존해서는 안되며, 둘 모두 추상화에 의존해야 함

추상화된 것에 의존하면 구체적인 구현 사항이 변경되어도 영향을 받지 않게 됨

## 의존 역전 원칙을 위반한 예시
class LightBulb:
    def turn_on(self):
        print("LightBulb: On")

    def turn_off(self):
        print("LightBulb: Off")

class Switch:
    def __init__(self, bulb):
        self.bulb = bulb

    def operate(self):
        self.bulb.turn_on()

bulb = LightBulb()
switch = Switch(bulb)
switch.operate()

 

## 의존 역전 원칙을 준수하도록 수정
# 추상화를 통해 의존성을 역전시킴
from abc import ABC, abstractmethod

class Switchable(ABC):
    @abstractmethod
    def turn_on(self):
        pass

    @abstractmethod
    def turn_off(self):
        pass

class LightBulb(Switchable):
    def turn_on(self):
        print("LightBulb: On")

    def turn_off(self):
        print("LightBulb: Off")

class Switch:
    def __init__(self, device):
        self.device = device

    def operate(self):
        self.device.turn_on()

bulb = LightBulb()
switch = Switch(bulb)
switch.operate()
728x90
728x90

프로그램 설계방법론의 일종으로, 명령형 프로그래밍에 속함

프로그램을 수많은 객체라는 기본 단위로 나누고, 이들의 상호작용으로 서술하는 방식

객체지향 프로그래밍을 사용하면 코드를 모듈화하고 유지보수하기 쉬움

클래스와 객체

클래스는 비슷한 특성을 가진 객체를 만드기 위한 일종의 틀

객체는 클래스를 기반으로 생성된 instance

객체는 "데이터"와 데이터를 처리하는 "메서드(함수)"를 포함

캡슐화

객체 내부의 데이터와 메서드는 외부에서 직접 접근하지 못하도록 제한되고, 필요한 경우에만 공개된 인터페이스를 통해 상호작용할 수 있도록 하는 원칙

class BankAccount:
    def __init__(self, balance=0):
        self._balance = balance  # _balance는 보호된 속성

    def deposit(self, amount):
        self._balance += amount

    def withdraw(self, amount):
        if amount <= self._balance:
            self._balance -= amount
        else:
            print("Insufficient funds")

    def get_balance(self):
        return self._balance

상속

클래스 간에 관계를 설정하여 기존 클래스의 특성과 동작을 재사용하고, 새로운 클래스를 정의
코드의 재사용성이 향상됨

class Animal:
    def __init__(self, name):
        self.name = name

    def make_sound(self):
        pass  # 하위 클래스에서 구현할 메서드

class Dog(Animal):
    def make_sound(self):
        return "Woof!"

class Cat(Animal):
    def make_sound(self):
        return "Meow!"

my_dog = Dog("Buddy")
my_cat = Cat("Whiskers")

print(my_dog.make_sound())  # 출력: Woof!
print(my_cat.make_sound())  # 출력: Meow!

다형성

같은 이름의 메서드를 각 객체에서 다르게 구현될 수 있는 특성
코드의 유연성을 증가시킴

class Shape:
    def area(self):
        pass  # 하위 클래스에서 구현할 메서드

class Square(Shape):
    def __init__(self, side_length):
        self.side_length = side_length

    def area(self):
        return self.side_length ** 2

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

square = Square(5)
circle = Circle(3)

print(square.area())  # 출력: 25
print(circle.area())  # 출력: 28.26

후속

파이썬 객체지향 5원칙

728x90

+ Recent posts