首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我编制了一个Python程序,根据通货膨胀率计算价格。

我编制了一个Python程序,根据通货膨胀率计算价格。
EN

Code Review用户
提问于 2020-04-23 04:54:11
回答 1查看 2K关注 0票数 1

我编制了一个程序,计算出在给定的几年内,由于通货膨胀,货币价值下降了多少。这需要一个本金,一个开始和结束日期,并且在通货膨胀率的帮助下,它计算货币在本年度的价值。(化合物)

CSV文件中的数据来自这里

这是密码-

代码语言:javascript
复制
import pandas

startDate = input("Enter the starting year ")
endDate = input("Enter the ending year ")

principal_amt = float(input("Enter the amount "))
startDate = startDate + "-12-" + "31"
endDate = endDate + "-12-" + "31"
final_amt = 0

print(startDate, endDate)

df = pandas.read_csv("india-cpi.csv")
df = df.set_index("date")

inflation_list = list(df.loc[startDate:endDate, " inflation-rate"])
print(inflation_list)

list_for_p = []
for item in inflation_list:
    principal_amt += principal_amt*(item/100)
    list_for_p.append(principal_amt)

print(list_for_p)
final_amt += principal_amt
print(final_amt)

这就是输出的样子:

进入2016年年初

进入2018年年底

输入金额100

2016-12-31 2018-12-31

4.941,2.4909,4.8607

104.941,107.554975369,112.782900056761

112.782900056761

我想问一下我的计算是否正确,如果你有其他的建议,请给我。会有帮助的。谢谢!

EN

回答 1

Code Review用户

发布于 2020-04-23 13:05:06

代码本身是足够清楚的,间距和变量命名是可以的。你把camelCasesnake_case混合在一起。坚持一个。PEP-8建议snake_case用于函数和变量名,PascalCase用于类。

只有principal_amt的缩写是相当徒劳的。只需使用全名,它要花费3个字符。

函数

你最好把你的程序按功能分开:

  • 读取数据
  • 获取用户输入
  • 计算差
  • 提出结果

这样,您的程序就更容易理解、测试和重用。

我关于在哪里拆分程序的经验法则是数据从一个部分交换到另一个部分的位置。

测试

现在,您已经在逻辑块中分隔了程序,您可以开始测试各个部分。

读取数据

创建一个小函数,将文件名作为参数传入,并每年将索引取回来。在这里,你可以进一步使用熊猫。首先,您可以将该年设置为pandas.Period,因此可以立即对该年进行索引。那么你已经可以进行除法了。由于熊猫有一个很好的cumprod函数,所以您可以在每个索引中添加1。

代码语言:javascript
复制
def get_inflation_rate(
    filename: typing.Union[Path, str, typing.IO]
) -> pd.Series:
    """Read the inflation data from `filename`"""
    inflation_rate = (
        pd.read_csv(
            data_file,
            skiprows=16,
            parse_dates=["date"],
            usecols=[0, 1],
            index_col=0,
        )
        .div(100)
        .add(1)
        .rename(columns={" Inflation Rate (%)": "inflation_rate"})
    )["inflation_rate"]
    inflation_rate.index = inflation_rate.index.to_period()
    return inflation_rate

这将返回一个以年份为指数,以通货膨胀率为值的系列。

代码语言:javascript
复制
date
1960    1.017799
1961    1.016952
1962    1.036322
1963    1.029462
...
2014    1.063532
2015    1.058724
2016    1.049410
2017    1.024909
2018    1.048607
Freq: A-DEC, Name: inflation_rate, dtype: float64

我包括了一个docstring和输入信息,这样这个函数的用户和他的IDE就可以知道期望什么了。

用户输入

如果您的用户返回一些废话,您的程序将没有什么用处。最好尽可能清楚地警告用户。您可以定义如下函数:

代码语言:javascript
复制
def get_input(
    *, message, possible_values: typing.Optional[typing.Collection[str]] = None
) -> str:
    while True:
        value = input(message)
        if possible_values is None or value in possible_values:
            return value
        print("Not one of the possibilities")

如果需要,也可以将其转换为浮点数,更一般的方法如下所示:

代码语言:javascript
复制
T = typing.TypeVar("T")


def get_input(
    *,
    message: str,
    possible_values: typing.Optional[typing.Collection[T]] = None,
    converter: typing.Optional[typing.Callable[[str], T]] = None,
) -> typing.Union[T, str]:
    """Get and convert the user input.

    Tries to call `converter` on the input value.
    If this raises a `ValueError`, asks again.

    If `possible_values` is defined, checks whether the returned value is in
    this collection. If it is not, asks again.

    Args:
        message (str): The message to present to the user.
        possible_values (typing.Collection[T], optional):
            A selection which must contain the user input. Defaults to None.
        converter (typing.Callable[[str], T], optional):
            A function to try to convert the user input. Defaults to None.

    Returns:
        typing.Union[T, str]: The converted user input.

    """
    while True:
        value = input(message)
        if converter is not None:
            try:
                value_converted = converter(value)
            except ValueError:
                print("Invalid value")
                continue
        else:
            value_converted = typing.cast(T, value)
        if possible_values is None or value_converted in possible_values:
            return value_converted
        print("Not one of the possibilities")

计算差分

由于已经有了以周期为指标的所有通货膨胀率的序列,这就很容易计算累积积,甚至接受datetime.datetime对象作为参数。

代码语言:javascript
复制
import datetime
def calculate_inflation(
    amount: float,
    start: typing.Union[datetime.datetime, str],
    end: typing.Union[datetime.datetime, str],
    inflation_rates: pd.Series,
) -> typing.Tuple[float, typing.Dict[str, float]]:
    inflation_over_period = inflation_rates[start:end]

    return (
        amount * inflation_over_period.product(),
        {
            str(year): amount * index
            for (year, index) in inflation_over_period.cumprod().iteritems()
        },
    )

把它结合在一起:

代码语言:javascript
复制
if __name__ == "__main__":
    data_file = Path("<my path>")
    inflation_rates = get_inflation_rate(data_file)
    start_year = get_input(
        message="Enter the starting year:",
        possible_values=set(inflation_rate.index.map(str)),
    )
    end_year = get_input(
        message="Enter the ending year:",
        possible_values={
            year for year in inflation_rate.index.map(str) if year > start_year
        },
    )
    amount = get_input(message="Specify the amount:", converter=float)
    print(
        calculate_inflation(
            amount=amount,
            start=start_year,
            end=end_year,
            inflation_rates=inflation_rates,
        )
    )
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/241046

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档