這是自己做的練習,可能有錯誤,歡迎討論和各種最佳化重構方案。
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 '-' + '$' + valueprint dollarize(-1234567.8901)
【參考】
函數format的應用來自這裡
http://www.qqread.com/other-devtool/z476049.html
(a)(b)代碼如下:
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)>>> cash123.45>>> print cash$123.45>>>>>> cash.update(100000.4567)Value has been updated, the new value is: 100000.4567>>> cash100000.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之說?也許是我理解錯誤,求指點。