If the price is always derivable from the symbol, I would go with a @property
. Keeps the code lean and it looks like an attribute from the outside:
def get_price(symbol):
return 123
@dataclass
class Stock:
symbol: str
@property
def price(self):
return get_price(symbol)
stock = Stock("NVDA")
print(stock.price) # 123
If you want to have a settable attribute that also has a default value that is derived from the other fields, you may just want to implement your own __init__
or __post_init__
as suggested.
If this is something you encounter a lot and need more sophisticated ways to handle it, I would recommend looking into pydantic and validator
s.
from typing import Optional
from pydantic import validator
from pydantic.dataclasses import dataclass
def get_price(symbol):
return 123.0
@dataclass
class Stock:
symbol: str
price: Optional[float] = None
@validator('price')
def validate_price(cls, v, values, **kwargs):
return v or get_price(values["symbol"])
print(Stock("NVDA"))
#> Stock(symbol='NVDA', price=123.0)
print(Stock("NVDA", 456))
#> Stock(symbol='NVDA', price=456.0)