在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ exercise48.更復(fù)雜的用戶輸入
附錄 A-練習(xí) 9:生成一個空文件(Touch, New-Item)
附錄 A-練習(xí) 10:復(fù)制文件 (cp)
exercise44.繼承 Vs.包含
附錄 A-練習(xí) 14:刪除文件 (rm)
附錄 A-練習(xí) 11:移動文件 (mv)
exercise46.項目骨架
附錄 A-練習(xí) 3:如果你迷路了
exercise37.復(fù)習(xí)符號
exercise47.自動化測試
exercise3.數(shù)字和數(shù)學(xué)計算
附錄 A-練習(xí) 1:安裝
exercise32.循環(huán)和列表
exercise31.做出決定
exercise42.對象、類、以及從屬關(guān)系
exercise48.更復(fù)雜的用戶輸入
下一步
簡介
附錄 A-練習(xí) 7:刪除路徑 (rmdir)
exercise49.寫代碼語句
exercise18.命名, 變量, 代碼, 函數(shù)
exercise12.提示別人
exercise14.提示和傳遞
exercise40.模塊, 類和對象
附錄 A-練習(xí) 12:查看文件 (less, MORE)
exercise9.打印, 打印, 打印
exercise13.參數(shù), 解包, 變量
exercise30. Else 和 If
exercise28. 布爾表達式
附錄 A-練習(xí) 4:創(chuàng)建一個路徑 (mkdir)
附錄 A-練習(xí) 15:退出命令行 (exit)
exercise25. 更多更多的練習(xí)
exercise6.字符串和文本
exercise2.注釋和井號“#”
exercise21. 函數(shù)的返回值
附錄 A-下一步
exercise1.第一個程序
exercise23. 閱讀代碼
附錄 A-練習(xí) 5:改變當前路徑 (cd)
exercise17.更多文件操作
exercise24. 更多的練習(xí)
exercise19.函數(shù)和變量
exercise51.從瀏覽器獲取輸入
exercise22. 到目前為止你學(xué)到了什么?
exercise41.學(xué)會說面向?qū)ο?/span>
exercise52.開始你的 web 游戲
exercise20. 函數(shù)和文件
exercise15.讀文件
exercise45.你來制作一個游戲
exercise10.那是什么?
exercise8.打印, 打印
exercise35.分支和函數(shù)
exercise26. 恭喜你,可以進行一次考試了
exercise33.while 循環(huán)
exercise29. IF 語句
exercise36.設(shè)計和調(diào)試
exercise0.安裝和準備
exercise50.你的第一個網(wǎng)站
附錄 A-練習(xí) 2:路徑, 文件夾, 名錄 (pwd)
exercise38.列表操作
附錄 A-練習(xí) 6:列出當前路徑 (ls)
exercise16.讀寫文件
exercise4.變量和命名
exercise34.訪問列表元素
exercise11.提問
exercise43.基本的面向?qū)ο蟮姆治龊驮O(shè)計
附錄 A-簡介
附錄 A-練習(xí) 8:目錄切換(pushd, popd)
來自老程序員的建議
exercise27. 記住邏輯
exercise5.更多的變量和打印
exercise7.更多的打印(輸出)
附錄 A-練習(xí) 13:輸出文件 (cat)
exercise39.字典,可愛的字典

exercise48.更復(fù)雜的用戶輸入

在以前的游戲中,你只是設(shè)置一些簡單的預(yù)定義字符串作為用戶輸入處理,用戶輸入“run”,程序能正常運行,但是你輸入“run fast”,程序就會運行失敗。我們需要一個設(shè)備,它可以識別用戶以各種方式輸入的語匯。例如下面的機種表述都應(yīng)該被支持才對:

  • open door
  • open the door
  • go THROUGH the door
  • punch bear
  • Punch The Bear in the FACE

也就是說,如果用戶的輸入和常用英語很接近也應(yīng)該是可以的,而你的游戲要識別出它們的意思。為了達到這個目的,我們將寫一個模塊專門做這件事情。這個模組里邊會有若干個類,它們互相配合,接受用戶輸入,并且將用戶輸入轉(zhuǎn)換成你的游戲可以識別的命令。

英語的簡單格式是這個樣子的:

  • 單詞由空格隔開。
  • 句子由單詞組成。
  • 語法控制句子的含義。

以最好的開始方式是先搞定如何得到用戶輸入的詞匯,并判斷出它們是什么。

我們的游戲詞典

我在游戲里創(chuàng)建了下面這些語匯:

  • 表示方向: north, south, east, west, down, up, left, right, back.
  • 動詞: go, stop, kill, eat.
  • 修飾詞: the, in, of, from, at, it
  • 名詞: door, bear, princess, cabinet.
  • 數(shù)字: 由 0-9 構(gòu)成的數(shù)字。

說到名詞,我們會碰到一個小問題,那就是不一樣的房間會用到不一樣的一組名詞,不過讓我們先挑一小組出來寫程序,以后再做改進。

如何斷句

我們已經(jīng)有了詞匯表,為了分析句子的意思,接下來我們需要找到一個斷句的方法。我們對于句子的定義是“空格隔開的單詞”,所以只要這樣就可以了:

stuff = raw_input('> ')
words = stuff.split()

目前做到這樣就可以了,不過這招在相當一段時間內(nèi)都不會有問題。

詞匯元組

一旦我們知道了如何將句子轉(zhuǎn)化成詞匯列表,剩下的就是逐一檢查這些詞匯,看它們是什么類型。為了達到這個目的,我們將用到一個非常好使的 Python 數(shù)據(jù)結(jié)構(gòu),叫做”元組(tuple)”。元組其實就是一個不能修改的列表。創(chuàng)建它的方法和創(chuàng)建列表差不多,成員之間需要用逗號隔開,不過方括號要換成圓括號 ():

first_word = ('verb', 'go')
second_word = ('direction', 'north')
third_word = ('direction', 'west')
sentence = [first_word, second_word, third_word]

這樣我們就創(chuàng)建了一個(TYPE,WORD)組,讓你識別出單詞,并且對它執(zhí)行指令。

這只是一個例子,不過最后做出來的樣子也差不多。你接受用戶輸入,用 split 將其分隔成單詞列表,然后分析這些單詞,識別它們的類型,最后重新組成一個句子。

掃描輸入

現(xiàn)在你要寫的是詞匯掃描器。這個掃描器會將用戶的輸入字符串當做參數(shù),然后返回由多個 (TOKEN, WORD) 組成的一個列表,這個列表實現(xiàn)類似句子的功能。如果一個單詞不在預(yù)定的詞匯表中,那它返回時 WORD 應(yīng)該還在,但 TOKEN 應(yīng)該設(shè)置成一個專門的錯誤標記。這個錯誤標記將告訴用戶哪里出錯了。

有趣的地方來了。我不會告訴你這些該怎樣做,但我會寫一個“單元測試(unit test)”,而你要把掃描器寫出來,并保證單元測試能夠正常通過。

異常和數(shù)字

有一件小事情我會先幫幫你,那就是數(shù)字轉(zhuǎn)換。為了做到這一點,我們會作一點弊,使用“異常(exceptions)”來做?!爱惓!敝傅氖悄氵\行某個函數(shù)時得到的錯誤。你的函數(shù)在碰到錯誤時,就會“拋出(raise)”一個“異?!?,然后你就要去處理(handle)這個異常。假如你在 Python 里寫了這些東西:

Python 2.7.1 (r271:86832, Jun 16 2011, 16:59:05) 
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> int("hell")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'hell'

這個 ValueError 就是 int()函數(shù)拋出的一個異常。因為你給 int() 的參數(shù)不是一個數(shù)字。int()函數(shù)其實也可以返回一個值來告訴你它碰到了錯誤,不過由于它只能返回整數(shù)值,所以很難做到這一點。它不能返回 -1,因為這也是一個數(shù)字。int()沒有糾結(jié)在它“究竟應(yīng)該返回什么”上面,而是提出了一個叫做 ValueError 的異常,然后你只要處理這個異常就可以了。

處理異常的方法是使用 try 和 except 這兩個關(guān)鍵字:

def convert_number(s):
    try:
        return int(s)
    except ValueError:
        return None

你把要試著運行的代碼放到 try 的區(qū)段里,再將出錯后要運行的代碼放到 except 區(qū)段里。在這里,我們要試著調(diào)用 int() 去處理某個可能是數(shù)字的東西,如果中間出了錯,我們就抓到這個錯誤,然后返回 None。

在你寫的掃描器里面,你應(yīng)該使用這個函數(shù)來測試某個東西是不是數(shù)字。做完這個檢查,你就可以聲明這個單詞是一個錯誤單詞了。

測試第一的挑戰(zhàn)

測試首先是一種編程策略,你先寫一段自動化測試代碼,假裝代碼是在正常運行的,然后你再寫出代碼保證測試代碼能正常運行。這種方法用在當你不知道代碼是如何運行,但又可以想象必須使用它的時候。比如說,如果你知道你需要在另一個模塊中使用一個新類,但是你不太知道如何實現(xiàn)這個類,那么先寫出測試程序。

我將給你一份測試代碼,你需要寫出代碼,保證測試代碼能正常工作。為了完成這個任務(wù),你可以看看下面的流程:

1.創(chuàng)建一小部分我給你的測試代碼 2.確保它運行失敗,你知道測試實際上是確認功能的工作原理。 3.到你的源代碼文件 lexicon.py 中,寫出能使測試代碼通過的代碼 4.重復(fù)以上工作直到你實現(xiàn)測試中的所有點

當你做到 3 的時候,和其他編寫代碼的方法相結(jié)合也是很好的方法:

1.編寫你需要的函數(shù)或類的基本框架 2.添加注釋,解釋說明這個函數(shù)是如何運行的 3.按照描述中的注釋寫代碼 4.去掉注釋

這種寫代碼的方法被稱作“psuedo code”,用在你不知道該如何實現(xiàn)某些功能,但是會用自己的語言來描述這個功能的時候。

結(jié)合“test first”和“psuedo code”策略,我們得出一個編程的簡易流程:

1.寫一些運行失敗的測試用例 2.寫出測試要用的函數(shù)、方法、類的基本結(jié)構(gòu) 3.用自己的語言填充這些框架,解釋它們的功能 4.用代碼替換注釋,直到測試代碼運行通過 5.重復(fù)

在這節(jié)練習(xí)中,你將通過運行我給你的測試程序逆向運行 lexicon.py 來實踐這個方法。

你應(yīng)該測試的東西

這里是你要用到的測試文件:

from nose.tools import *
from ex48 import lexicon

def test_directions():
    assert_equal(lexicon.scan("north"), [('direction', 'north')])
    result = lexicon.scan("north south east")
    assert_equal(result, [('direction', 'north'),
                          ('direction', 'south'),
                          ('direction', 'east')])

def test_verbs():
    assert_equal(lexicon.scan("go"), [('verb', 'go')])
    result = lexicon.scan("go kill eat")
    assert_equal(result, [('verb', 'go'),
                          ('verb', 'kill'),
                          ('verb', 'eat')])

def test_stops():
    assert_equal(lexicon.scan("the"), [('stop', 'the')])
    result = lexicon.scan("the in of")
    assert_equal(result, [('stop', 'the'),
                          ('stop', 'in'),
                          ('stop', 'of')])

def test_nouns():
    assert_equal(lexicon.scan("bear"), [('noun', 'bear')])
    result = lexicon.scan("bear princess")
    assert_equal(result, [('noun', 'bear'),
                          ('noun', 'princess')])

def test_numbers():
    assert_equal(lexicon.scan("1234"), [('number', 1234)])
    result = lexicon.scan("3 91234")
    assert_equal(result, [('number', 3),
                          ('number', 91234)])

def test_errors():
    assert_equal(lexicon.scan("ASDFADFASDF"), [('error', 'ASDFADFASDF')])
    result = lexicon.scan("bear IAS princess")
    assert_equal(result, [('noun', 'bear'),
                          ('error', 'IAS'),
                          ('noun', 'princess')])

你需要用項目框架寫出一個新的項目,就像你在練習(xí) 47 中做的一樣。然后你需要創(chuàng)建這個測試用例以及你會用到的 lexicon.py,看看測試用例頂部,看看它是如何被導(dǎo)入的。

接下來,按照我給你的提示寫一些測試用例??纯次沂侨绾巫龅模?/p>

1.在測試用例頂部寫上導(dǎo)入(import),并保證它正常運行 2.創(chuàng)建第一個測試用例 test_directions 的空版本,并保證它正常運行 3.寫出測試用例 test_directions 的第一行,保證它運行失敗 4.到 lexicon.py 文件,創(chuàng)建一個空的 scan 方法 5.運行測試用例,至少保證 scan 方法運行,即便測試用例運行失敗 6.為 scan 寫出偽代碼注釋,用來說明 scan 如何通過 test_directions 測試 7.寫出與注釋相匹配的代碼,保證 test_directions 測試通過 8.回到方法 test_directions,寫完剩下的行 9.回到 lexicon.py 中的 scan 方法,補全代碼直到 test_directions 測試通過 10.這樣,當你的第一個測試通過,你移動到下一個測試重復(fù)以上步驟。

只要你堅持在每次執(zhí)行此過程中的一小塊,你可以成功將大問題分解成更小的問題來解決。就像爬山的時候,你把整段路程分成一小段一小段。

附加題

1.改進單元測試,讓它覆蓋到更多的語匯。 2.向語匯列表添加更多的語匯,并且更新單元測試代碼。 3.讓你的掃描器能夠識別任意大小寫的詞匯。更新你的單元測試。 4.找出另外一種轉(zhuǎn)換為數(shù)字的方法。 5.我的解決方案用了 37 行代碼,你的是更長還是更短呢?

常見問題

Q: 為什么我一直有這個報錯 ImportErrors?

導(dǎo)入異常通常有以下幾點原因:1,在你的模塊(modules)目錄下沒有生成init.py 文件;2,你在錯誤的目錄下啟動服務(wù);3,你導(dǎo)入的模塊有拼寫錯誤;4,你的 PYTHONPATH 沒有設(shè)置成.。

Q: try-except 和 if-else 有什么區(qū)別?

try-expect 是用來處理模塊拋出的異常,永遠都不能用 if-else 代替。

Q: 有沒有辦法能實現(xiàn)在等待用戶輸入的時候,游戲也一樣運行

我假設(shè)一種情況,你想實現(xiàn)用戶在反應(yīng)不夠快的情況下會遭到怪物的攻擊,這是可能的,但是它涉及的模塊和技術(shù)是本書范圍之外的。