这是自己做的练习,可能有错误,欢迎讨论和各种优化重构方案。
13-3.
对类进行定制。写一个类,用来将浮点型值转换为金额。在本练习里,我们使用美国货币,但读者也可以自选任意货币。
基本任务(α):编写一个dollarize()函数,它以一个浮点型值作为输入,返回一个字符串形式的金额数。比如说:
dollarize(1234567.8901) => '$1,234,567.89'
dollarize()返回的金额数里应该允许有逗号(比如1,000,000)和美元的货币符号。如果有负号,它必须出现在美元符号的左边。完成这项工作后,你就可以把它转换成一个有用的类,名为MoneyFmt。
MoneyFmt类里只有一个数据值(即金额),和5个方法(你可以随意编写其他方法)。__init__()构造器对数据进行初始化,update()方法把数据值替换成一个新值。__nonzero__()是布尔型的,当数据值非零时返回True,__repr__()方法以浮点型的形式返回金额;而__str__()方法采用和dollarize()一样的字符格式显示该值。
(a)编写update()方法,以实现数据值得修改功能。
(b)以你已经编写的dollarize()函数的代码为基础,编写__str__()方法的代码。
(c)纠正例子13.11,moneyfmt.py中__nonzero__()方法中的错误,这个错误认为所有小于1的数值,例如,50美分($0.50),返回假值(False)。金额转换程序(moneyfmt.py)的主要代码如例13.11所示。
(d)附加题:允许用户通过一个可选参数指定是把负数数值显示在一对尖括号里还是显示一个符号。默认参数是使用标准的负号。
例13.11 金额转换程序(moneyfmt.py)
字符串格式类用来对浮点型值进行“打包”,使整个数值显示为带有正确符号的金额。
#-*- encoding: utf-8 -*- class MoneyFmt(object): def __init__(self, value = 0.0): # constructor self.value = float(value) def update(self, value = None): # allow updates ### ### (a) cpmplete this function ### def __repr__(self): # display as a float return repr(self.value) # 这里的修改参考了英文版原书 def __str__(self): # formatted display val = '' ### ### (b) complete this function ... do NOT ### forget about negative numbers!! ### return val def __nonzero__(self): # boolean test ### ### (c) find and fix the bug ### return int(self.value)
【答案】
(α)函数dollarize()相关代码如下:
def dollarize(i): roundi = round(i, 2) absi = abs(roundi) if (absi * 10) % 1 == 0: value = format(absi, ',') + '0' else: value = format(absi, ',') if roundi >= 0: return '$' + value else: return '-' + '$' + value print dollarize(-1234567.8901)
【参考】
函数format的应用来自这里
http://www.qqread.com/other-devtool/z476049.html
class MoneyFmt(object): def __init__(self, value = 0.0): # constructor self.value = float(value) def update(self, value = None): # allow updates ### (a) Begins if value != None: self.value = float(value) print 'Value has been updated, the new value is: ', self.value else: print 'Value has not been updated.' ### (a) Ends def __repr__(self): # display as a float return repr(self.value) def __str__(self): # formatted display val = '' ### (b) Begins roundi = round(self.value, 2) absi = abs(roundi) if (absi * 10) % 1 == 0: value = format(absi, ',') + '0' else: value = format(absi, ',') if roundi >= 0: val = '$' + value else: val = '-' + '$' + value ### (b) Ends return val def __nonzero__(self): # boolean test ### ### (c) find and fix the bug ### return int(self.value)
【注】
运行前,将上面的代码保存为moneyfmt.py文件。在Python27文件夹中,新建一个文件夹PrivateLib,将这个文件拷贝进去。
【(a)(b)代码运行结果】
>>> import sys >>> sys.path.append('d:\\python27\privatelib') >>> >>> import moneyfmt >>> >>> cash = moneyfmt.MoneyFmt(123.45) >>> cash 123.45 >>> print cash $123.45 >>> >>> cash.update(100000.4567) Value has been updated, the new value is: 100000.4567 >>> cash 100000.4567 >>> print cash $100,000.46 >>> >>> cash.update(-0.3) Value has been updated, the new value is: -0.3 >>> cash -0.3 >>> print cash -$0.30 >>> repr(cash) '-0.3' >>> 'cash' # 这是唯一和原书上不一致的地方。但我怀疑是原书错误。 'cash' >>> str(cash) '-$0.30' >>>
(d)代码如下:
class MoneyFmt(object): def __init__(self, value = 0.0, flag = '-'): # constructor self.value = float(value) self.flag = flag def update(self, value = None): # allow updates ### (a) Begins if value != None: self.value = float(value) print 'Value has been updated, the new value is: ', self.value else: print 'Value has not been updated.' ### (a) Ends def __repr__(self): # display as a float return repr(self.value) def __str__(self): # formatted display val = '' ### (b) Begins roundi = round(self.value, 2) absi = abs(roundi) if (absi * 10) % 1 == 0: value = format(absi, ',') + '0' else: value = format(absi, ',') if roundi >= 0: val = '$' + value else: val = self.flag + '$' + value ### (b) Ends return val def __nonzero__(self): # boolean test ### ### (c) find and fix the bug ### return int(self.value)
【注】
运行前,将上面的代码保存为moneyfmtd.py文件。在Python27文件夹中,新建一个文件夹PrivateLib,将这个文件拷贝进去。
【(d)代码运行结果】
>>> import sys >>> sys.path.append('d:\\Python27\\PrivateLib') >>> import moneyfmtd >>> cash1 = moneyfmtd.MoneyFmt(123.45) >>> print cash1 $123.45 >>> cash2 = moneyfmtd.MoneyFmt(-123.45) >>> print cash2 -$123.45 >>> cash3 = moneyfmtd.MoneyFmt(-123.45, '<->') >>> print cash3 <->$123.45 >>> cash3.update(-0.3) Value has been updated, the new value is: -0.3 >>> print cash3 <->$0.30 >>>
【未完】
(c)没有完成。题目在__nonzero__()方法中未显示任何代码,何来修改bug之说?也许是我理解错误,求指点。