<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    15.4. 后記

                    聰明的讀者在學習前一節時想得會更深入一層。現在寫的這個程序中最令人頭痛的性能負擔是正則表達式,但它是必需的,因為沒有其它方法來識別羅馬數字。但是,它們只有 5000 個,為什么不一次性地構建一個查詢表來讀取?不必用正則表達式凸現了這個主意的好處。你建立了整數到羅馬數字查詢表的時候,羅馬數字到整數的逆向查詢表也構建了。

                    更大的好處在于,你已經擁有一整套完全的單元測試。你修改了多半的代碼,但單元測試還是一樣的,因此你可以確定你的新代碼與來的代碼一樣可以正常工作。

                    例 15.17. roman9.py

                    這個文件可以在例子目錄下的 py/roman/stage9/ 目錄中找到。

                    如果您還沒有下載本書附帶的樣例程序, 可以 下載本程序和其他樣例程序

                    #Define exceptions
                    class RomanError(Exception): pass
                    class OutOfRangeError(RomanError): pass
                    class NotIntegerError(RomanError): pass
                    class InvalidRomanNumeralError(RomanError): pass
                    
                    #Roman numerals must be less than 5000
                    MAX_ROMAN_NUMERAL = 4999
                    
                    #Define digit mapping
                    romanNumeralMap = (('M',  1000),
                                       ('CM', 900),
                                       ('D',  500),
                                       ('CD', 400),
                                       ('C',  100),
                                       ('XC', 90),
                                       ('L',  50),
                                       ('XL', 40),
                                       ('X',  10),
                                       ('IX', 9),
                                       ('V',  5),
                                       ('IV', 4),
                                       ('I',  1))
                    
                    #Create tables for fast conversion of roman numerals.
                    #See fillLookupTables() below.
                    toRomanTable = [ None ]  # Skip an index since Roman numerals have no zero
                    fromRomanTable = {}
                    
                    def toRoman(n):
                        """convert integer to Roman numeral"""
                        if not (0 < n <= MAX_ROMAN_NUMERAL):
                            raise OutOfRangeError, "number out of range (must be 1..%s)" % MAX_ROMAN_NUMERAL
                        if int(n) <> n:
                            raise NotIntegerError, "non-integers can not be converted"
                        return toRomanTable[n]
                    
                    def fromRoman(s):
                        """convert Roman numeral to integer"""
                        if not s:
                            raise InvalidRomanNumeralError, "Input can not be blank"
                        if not fromRomanTable.has_key(s):
                            raise InvalidRomanNumeralError, "Invalid Roman numeral: %s" % s
                        return fromRomanTable[s]
                    
                    def toRomanDynamic(n):
                        """convert integer to Roman numeral using dynamic programming"""
                        result = ""
                        for numeral, integer in romanNumeralMap:
                            if n >= integer:
                                result = numeral
                                n -= integer
                                break
                        if n > 0:
                            result += toRomanTable[n]
                        return result
                    
                    def fillLookupTables():
                        """compute all the possible roman numerals"""
                        #Save the values in two global tables to convert to and from integers.
                        for integer in range(1, MAX_ROMAN_NUMERAL + 1):
                            romanNumber = toRomanDynamic(integer)
                            toRomanTable.append(romanNumber)
                            fromRomanTable[romanNumber] = integer
                    
                    fillLookupTables()
                    

                    這樣有多快呢?

                    例 15.18. 用 romantest9.py 測試 roman9.py 的結果

                    
                    .............
                    ----------------------------------------------------------------------
                    Ran 13 tests in 0.791s
                    
                    OK
                    
                    

                    還記得嗎?你原有版本的最快速度是 13 個測試耗時 3.315 秒。當然,這樣的比較不完全公平,因為這個新版本需要更長的時間來導入 (當它填充查詢表時)。但是導入只需一次,在運行過程中可以忽略。

                    這個重構的故事的寓意是什么?

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频