任务描述
本关主题是利用 Python 面向对象编程技术,对按揭贷款的问题,进行面向对象建模与编程。请仔细阅读下面“相关知识”中的内容,理解每个函数所需完成的操作,补全相关函数,以实现计算按揭贷款的要求。
相关知识
2008 年美国的次贷危机导致全球经济下滑,至今还未完全恢复。次贷危机的一个因素是很多房主都采用按揭贷款( Mortgage )来购房,而未考虑按揭贷款带来的不可预知的后果。
早期的按揭贷款非常简单,房主从银行借钱,然后在接下来的 15~30 年间,每月向银行支付一个固定额度还钱。贷款到期后,银行收回借款和一定的利息,而房主完全地拥有了住房。
20 世纪末期,按揭贷款变得复杂了,人们可以选择在按揭开始时,支付“ 几个点 ”以降低贷款利率, 1 个点指的是贷款额的 1% ;或者选择多利率贷款,通常初始利息率非常低(称为引诱利率),然后慢慢攀升,因此每个月还给银行的钱是不固定的。尽管提供多种贷款方式供选择是好事,但是无良的放贷商通常不会详细解释各种贷款方式的长远影响,这往往会给贷款者将来的生活造成重大的影响。
为了了解按揭贷款的规则,我们可以将这些规则变成计算机能理解的程序语句,然后利用计算机问题求解,来帮助人们选择合适的贷款方式。下面考虑三种贷款方式:
固定利息率,不支付任何点;
固定利息率,支付一定的点;
可变利息率,低引诱利率,随后高利息率。
本关中,我们利用面向对象的程序设计技术,来研究按揭贷款:各种贷款选择除了有共同点(每次贷款包含本金和利息)外,又有不同点(如利率、是否支付点等),因此可将按揭贷款中的贷款,设计成一个类 Mortgage ,而 3 种贷款设计成它的子类。由于贷款类并不作具体的,诸如计算利息等这类计算,故可以将其设计成抽象类( abst\fract class ),只包含必要的供子类使用的函数,而不做具体的实现,也不建议直接实例化这个类。
接下来我们对 Mortgage 类和函数 findPayment 进行说明:
每月应支付给银行的还款由函数 findPayment 计算,公式为:
loan∗
(1+r)
m
−1
r∗(1+r)
m
其中:loan 为贷款额, r 是月利息率, m 是贷款月数。
Mortgage 对象初始化时,需要指定贷款额( loan )、月利息率( rate )、贷款期限( months ,以月计),以及每月开始时—即到该月—已经支付的金额( paid ,是一个列表)、每月开始时还剩的贷款额( owed ,是一个列表)、每月应付金额(payment ),以及对贷款类型的描述( legend )。 init 函数中的参数 loan 为贷款额, months 为还款月数, annRate 为年利息。例如年利息为 6.5% ,则初始化时,annRate 的值为 6.5;
makePayment 方法用于记录贷款的支付情况,每月支付给银行的金额,一部分用于支付利息,一部分用于归还本金。首先,在 paid 中,添加当月还款金额;然后,用前一月结束时,还欠银行的钱减去上一个月的利息,即为本月已还的本金。则本月还欠银行的本金,为上月本金减去本月已还本金。因此,该方法中,同时对 paid 和 owed 属性值进行了修改;
getTotalPaid 方法用于计算支付给银行的本金和利息总额。
编程要求
本关的编程任务是补全 7-1.py 文件中 findPayment 、init 、 makePayment 以及 getTotalPaid 四个函数,以实现计算按揭贷款的要求。具体要求如下:
本关要求补全上述描述的 4 个函数,并通过研究按揭贷款的规则,来帮助人们选择合适的贷款方式;
具体请参见后续测试样例。
本关涉及的代码文件7-1.py的代码框架如下:
def findPayment(loan, r, m):
# 请在此添加代码,补全函数findPayment
#********** Begin #
#* End #
class Mortgage(object):
def init(self, loan, annRate, months):
# 请在此添加代码,补全函数__init__
#* Begin #
#* End #
self.legend = None
def makePayment(self):
# 请在此添加代码,补全函数makePayment
#* Begin #
#* End #
def getTotalPaid(self):
# 请在此添加代码,补全函数getTotalPaid
#* Begin #
#* End *********#
def str(self):
return ‘The Mortgage is {self.legend}, Loan is {self.loan}, Months is {self.months}, Rate is {self.rate:.2f}, Monthly payment is {self.payment:.2f}’.format(self=self)
if name==“main”:
print(Mortgage(100000, 6.5, 36))
print(Mortgage(100000, 6.5, 120))
测试说明
平台会对你编写的代码进行测试:
测试输入:无输入
预期输出:
The Mortgage is None, Loan is 100000, Months is 36, Rate is 0.01, Monthly payment is 3064.90
The Mortgage is None, Loan is 100000, Months is 120, Rate is 0.01, Monthly payment is 1135.48
开始你的任务吧,祝你成功!
每一个成功者都有一个开始。勇于开始,才能找到成功的路。
代码示例
def findPayment(loan, r, m):
#********** Begin *********#
# 请在下面编写代码
return loan*((r * (1+r) ** m) / ((1+r) ** m -1))
# 请不要修改下面的代码
#********** End *********#
class Mortgage(object):
def __init__(self, loan, annRate, months):
#********** Begin *********#
# 请在下面编写代码
self.loan = loan
self.annRate = annRate
self.months = months
self.rate = self.annRate/12/100
self.paid = [0.0]
self.owed = [loan]
self.payment = findPayment(loan,self.rate,months)
# 请不要修改下面的代码
#********** End *********#
self.legend = None
def makePayment(self):
#********** Begin *********#
# 请在下面编写代码
self.paid.append(self.payment)
reduction = self.payment - self.owed[-1] * self.rate
self.owed.append(self.owed[-1] - reduction)
# 请不要修改下面的代码
#********** End *********#
def getTotalPaid(self):
#********** Begin *********#
# 请在下面编写代码
return sum(self.paid)
# 请不要修改下面的代码
#********** End *********#
def __str__(self):
return 'The Mortgage is {self.legend}, Loan is {self.loan}, Months is {self.months}, Rate is {self.rate:.2f}, Monthly payment is {self.payment:.2f}'.format(self=self)
if __name__=="__main__":
print(Mortgage(100000, 6.5, 36))
print(Mortgage(100000, 6.5, 120))