[카테고리:] 미분류

  • python dataclasses

    📌 적합한 자료형 후보

    1. dict (딕셔너리): 각 종목마다 세부 항목(key: value) 관리
    2. dataclass (Python 3.7+): 구조화된 객체 사용 + 가독성 ↑
    3. custom class: 사용자 정의 객체로 세밀한 제어 가능
    4. NamedTuple or TypedDict: 타입 안정성 필요할 때 유용 (정적 타입 검사기 사용 시)

    ✅ 최적 구조: dataclass + dict[str, StockInfo]

    • 종목별 정보를 dataclass로 구조화
    • 전체 주식 정보는 종목명(key) 기준의 dict로 관리

    💡 구현 예시

    from dataclasses import dataclass, asdict
    from typing import Dict
    
    @dataclass
    class StockInfo:
        code: str
        price: int
        market_cap: int
        per: float
    
    class GlobalStockStorage:
        global_stocks: Dict[str, StockInfo] = {
            "삼성전자": StockInfo(code="005930", price=70000, market_cap=450_000_000_000_000, per=15.2)
        }
    
        def __init__(self, **additional_stocks: StockInfo):
            # 클래스 변수 복사 → 인스턴스 독립적 상태 유지
            self.stocks = self.global_stocks.copy()
            self.stocks.update(additional_stocks)
    
        def show_all(self):
            for name, stock in self.stocks.items():
                print(f"[{name}]")
                for k, v in asdict(stock).items():
                    print(f"  {k}: {v}")
                print()
    
    # Example usage
    test = GlobalStockStorage(
        카카오=StockInfo(code="035720", price=54000, market_cap=48000000000000, per=23.4),
        네이버=StockInfo(code="035420", price=210000, market_cap=34000000000000, per=35.1),
    )
    test.show_all()
    

    🧾 출력 예시:

    [삼성전자]
      code: 005930
      price: 70000
      market_cap: 450000000000000
      per: 15.2
    
    [카카오]
      code: 035720
      price: 54000
      market_cap: 48000000000000
      per: 23.4
    
    [네이버]
      code: 035420
      price: 210000
      market_cap: 34000000000000
      per: 35.1
    

    🧠 요약

    목적적합한 자료형
    종목별 세부 항목 다수 관리dataclass + dict
    읽기전용, 가벼운 구조NamedTuple
    JSON 직렬화 고려asdict() or __dict__
    정적 타입 검사TypedDict (with mypy 등)

    JSON으로 저장/로드


    ✅ 목표 기능

    1. 종목 정보를 StockInfo 데이터클래스로 구조화
    2. GlobalStockStorage 클래스로 추가/출력 관리
    3. JSON 파일로 저장 및 로드 기능 포함

    🧾 전체 코드

    import json
    from dataclasses import dataclass, asdict, fields
    from typing import Dict
    
    # 1. 개별 종목 정보를 담는 데이터 클래스
    @dataclass
    class StockInfo:
        code: str
        price: int
        market_cap: int
        per: float
    
        @staticmethod
        def from_dict(data: dict) -> 'StockInfo':
            return StockInfo(**{f.name: data[f.name] for f in fields(StockInfo)})
    
    # 2. 전체 종목 리스트를 관리하는 클래스
    class GlobalStockStorage:
        global_stocks: Dict[str, StockInfo] = {
            "삼성전자": StockInfo(code="005930", price=70000, market_cap=450_000_000_000_000, per=15.2)
        }
    
        def __init__(self, **additional_stocks: StockInfo):
            self.stocks = self.global_stocks.copy()
            self.stocks.update(additional_stocks)
    
        def show_all(self):
            for name, stock in self.stocks.items():
                print(f"[{name}]")
                for k, v in asdict(stock).items():
                    print(f"  {k}: {v}")
                print()
    
        def save_to_json(self, filepath: str):
            json_data = {name: asdict(stock) for name, stock in self.stocks.items()}
            with open(filepath, "w", encoding="utf-8") as f:
                json.dump(json_data, f, ensure_ascii=False, indent=2)
            print(f"📁 저장 완료: {filepath}")
    
        @classmethod
        def load_from_json(cls, filepath: str) -> 'GlobalStockStorage':
            with open(filepath, "r", encoding="utf-8") as f:
                json_data = json.load(f)
            loaded_stocks = {name: StockInfo.from_dict(data) for name, data in json_data.items()}
            return cls(**loaded_stocks)
    

    ▶️ 사용 예시

    # 초기 객체 생성 및 저장
    storage = GlobalStockStorage(
        카카오=StockInfo(code="035720", price=54000, market_cap=48000000000000, per=23.4),
        네이버=StockInfo(code="035420", price=210000, market_cap=34000000000000, per=35.1),
    )
    storage.save_to_json("stocks.json")  # JSON 파일로 저장
    
    # 다른 시점에서 로드
    loaded = GlobalStockStorage.load_from_json("stocks.json")
    loaded.show_all()
    

    🧠 보충 설명

    항목설명
    asdict()dataclass 객체 → dict 변환
    from_dict()dict → dataclass 객체 생성
    json.dump()파일에 JSON으로 저장
    json.load()파일에서 JSON 읽기

    이 구조는 확장성, 직렬화 호환성, 가독성이 뛰어나서 실제 주식 관리 앱이나 백엔드 API 설계 시에도 그대로 적용 가능합니다.

    좋습니다! 지금까지 만든 구조(dataclass + dict)를 Pandas와 연동하면 아래와 같은 작업이 가능합니다:

    • dict[str, StockInfo]DataFrame으로 변환
    • DataFramedict[str, StockInfo]로 역변환
    • CSV/Excel 등 다양한 포맷 입출력 가능

    ✅ 전체 연동 기능 구현: Pandas 통합 버전

    import json
    import pandas as pd
    from dataclasses import dataclass, asdict, fields
    from typing import Dict
    
    # 1. 데이터 클래스 정의
    @dataclass
    class StockInfo:
        code: str
        price: int
        market_cap: int
        per: float
    
        @staticmethod
        def from_dict(data: dict) -> 'StockInfo':
            return StockInfo(**{f.name: data[f.name] for f in fields(StockInfo)})
    
    # 2. 메인 저장 클래스
    class GlobalStockStorage:
        global_stocks: Dict[str, StockInfo] = {
            "삼성전자": StockInfo(code="005930", price=70000, market_cap=450_000_000_000_000, per=15.2)
        }
    
        def __init__(self, **additional_stocks: StockInfo):
            self.stocks = self.global_stocks.copy()
            self.stocks.update(additional_stocks)
    
        def show_all(self):
            for name, stock in self.stocks.items():
                print(f"[{name}]")
                for k, v in asdict(stock).items():
                    print(f"  {k}: {v}")
                print()
    
        def save_to_json(self, filepath: str):
            json_data = {name: asdict(stock) for name, stock in self.stocks.items()}
            with open(filepath, "w", encoding="utf-8") as f:
                json.dump(json_data, f, ensure_ascii=False, indent=2)
    
        @classmethod
        def load_from_json(cls, filepath: str) -> 'GlobalStockStorage':
            with open(filepath, "r", encoding="utf-8") as f:
                json_data = json.load(f)
            loaded_stocks = {name: StockInfo.from_dict(data) for name, data in json_data.items()}
            return cls(**loaded_stocks)
    
        # ✅ 판다스 변환 기능
        def to_dataframe(self) -> pd.DataFrame:
            data = {name: asdict(stock) for name, stock in self.stocks.items()}
            df = pd.DataFrame.from_dict(data, orient='index')
            df.index.name = '종목명'
            return df
    
        @classmethod
        def from_dataframe(cls, df: pd.DataFrame) -> 'GlobalStockStorage':
            df = df.reset_index()
            stocks = {
                row['종목명']: StockInfo(
                    code=row['code'],
                    price=int(row['price']),
                    market_cap=int(row['market_cap']),
                    per=float(row['per'])
                )
                for _, row in df.iterrows()
            }
            return cls(**stocks)
    

    ▶️ 사용 예시

    # 초기 생성
    storage = GlobalStockStorage(
        카카오=StockInfo(code="035720", price=54000, market_cap=48000000000000, per=23.4),
        네이버=StockInfo(code="035420", price=210000, market_cap=34000000000000, per=35.1),
    )
    
    # Pandas DataFrame 변환
    df = storage.to_dataframe()
    print(df)
    
    # 저장
    df.to_csv("stocks.csv", encoding="utf-8-sig")  # CSV 저장
    
    # CSV 불러오기 후 객체 재생성
    df_loaded = pd.read_csv("stocks.csv", index_col="종목명")
    storage2 = GlobalStockStorage.from_dataframe(df_loaded)
    
    # 재확인
    storage2.show_all()
    

    📊 출력 예시 (DataFrame)

                  code   price    market_cap   per
    종목명                                        
    삼성전자     005930   70000  450000000000000  15.2
    카카오      035720   54000   48000000000000  23.4
    네이버      035420  210000   34000000000000  35.1
    

    ✅ 요약

    작업 내용함수
    dict → DataFrame.to_dataframe()
    DataFrame → dictfrom_dataframe()
    JSON 저장/로드save_to_json, load_from_json
    CSV 저장/로드DataFrame.to_csv, pd.read_csv()