python - 使用 attrs 创建具有互斥参数的 Python 类
问题描述
我有一个有两个互斥参数(prices
和returns
)的类。也就是说,不能同时提供它们以实例化对象。
但是,该类需要两者进行内部计算。所以我想计算pd.Series
用户提供的缺失值。
我创建了两个替代类构造函数(from_prices
和from_returns
)。使用这些构造函数,该类将被正确实例化。
这是代码。它利用了attrs
库 ( www.attrs.org )。
import pandas as pd
import attr
@attr.s
class MutuallyExclusive:
prices: pd.Series = attr.ib()
returns: pd.Series = attr.ib()
trading_days_per_year: int = attr.ib(default=252)
@classmethod
def from_prices(cls, price_series: pd.Series, trading_days: int = 252):
return cls(
price_series,
price_series.pct_change(),
trading_days,
)
@classmethod
def from_returns(cls, return_series: pd.Series):
return cls(
pd.Series(data=100 + 100 * (returns.add(1).cumprod() - 1)),
return_series,
)
if __name__ == "__main__":
prices = pd.Series(data=[100, 101, 98, 104, 102, 108])
returns = pd.Series(data=[0.01, 0.03, -0.02, 0.01, -0.03, 0.04])
obj_returns = MutuallyExclusive.from_returns(returns)
obj_prices = MutuallyExclusive.from_prices(prices, trading_days=100)
obj = MutuallyExclusive(prices, returns)
但是,即使这两个系列彼此不兼容,用户仍然可以调用。捕捉这种情况并引发错误的最佳方法是什么?
编辑:
是否可以一起“禁用”常规构造函数?如果可以仅通过替代构造函数实例化对象,这将解决问题,不是吗?
解决方案
图书馆是attrs
正确的工具吗?为什么不使用常规的 python 类并定义__init__()
自己?
import pandas as pd
class MutuallyExclusive:
def __init__(self, prices: pd.Series = None, returns: pd.Series = None):
if prices is not None and returns is not None:
raise ValueError("prices and returns are mutually exclusive")
self.prices = prices if prices is not None else pd.Series(data=100 * (1 + returns))
self.returns = returns if returns is not None else prices.pct_change()
if __name__ == "__main__":
prices = pd.Series(data=[100, 101, 98, 104, 102, 108])
returns = pd.Series(data=[0.01, 0.03, -0.02, 0.01, -0.03, 0.04])
obj_returns = MutuallyExclusive(returns=returns)
obj_prices = MutuallyExclusive(prices=prices)
编辑:您更新了您的示例,因此我的答案缺少 trading_days_per_year
但概念是相同的。
如果您想使用该attrs
库,其他人指出您可以将您的逻辑放在__attrs_post_init__
函数中,请参见下面的示例删除对类方法的需要注意您需要默认价格和返回None
def __attrs_post_init__(self):
if self.prices is not None and self.returns is not None:
raise ValueError("prices and returns are mutually exclusive")
if self.returns is None:
self.returns = self.price_series.pct_change()
if self.prices is None:
self.prices = pd.Series(data=100 + 100 * (self.returns.add(1).cumprod() - 1))
推荐阅读
- nosql - 如何将 GraphQL 用于企业应用程序
- android - 如何在 Android Studio 中的完整 RecyclerView(不是项目)上实现向下滑动手势?
- tcl - 期望 - 如何为动态变量“发送用户”
- dotnetnuke - DNN返回父页面而不是404页面,如何返回404?
- antlr4 - 在跳过空格的同时将单个单词解析为多个标记
- php - Opencart 3 - 在向管理员注册电子邮件时显示自定义字段
- hive - 如何使用气流将 Hive Operator 输出导出到本地 csv 文件?
- kamailio - 如何在 homer 数据库中保存超过 1500 个字符的数据
- php - 在小部件上的 WordPress 图像中将“src”属性更改为“data-src”
- c - 使用 VS Studio 调试非常大的文件