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์œผ๋กœ ๋ณ€ํ™˜
  • DataFrame โ†’ dict[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()

์ฝ”๋ฉ˜ํŠธ

๋‹ต๊ธ€ ๋‚จ๊ธฐ๊ธฐ

์ด๋ฉ”์ผ ์ฃผ์†Œ๋Š” ๊ณต๊ฐœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•„์ˆ˜ ํ•„๋“œ๋Š” *๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค