2014-02-10 23 views
2

我正在學習Python的困難的方法運動48和寫入lexicon字典和scan模塊上運行以下測試:「開放式」字典鍵? (LPTHW鍛鍊48相關)

from nose.tools import * 
from ex47 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')]) 

我最該想通的除數字和錯誤測試外。如果用戶輸入是詞典中未定義的單詞,則需要使用error值名稱進行標記,如果是數字 - number值名稱。顯然,我可以預先將所有要測試的輸入添加到字典中,但這是作弊。

我的字典裏是這樣的:

lexicon = { 
    'north': 'direction', 
    'princess': 'noun', 
    # etc... 
} 

有沒有辦法工作,呃,數字和不確定的話這個「開放式」的定義?

UPDATE。這裏是一個有效的解決方案:

def scan(sentence): 
    words = sentence.split() 
    pairs = [] 

    for word in words: 
     try: 
      number = int(word) 
      tupes = ('number', number) 
      pairs.append(tupes) 

     except ValueError: 
      try: 
       word_type = lexicon[word] 
       tupes = (word_type, word) 
       pairs.append(tupes) 
      except KeyError: 
       tupes = ('error', word) 
       pairs.append(tupes) 
    return pairs 
+0

您的解決方案看起來不錯。我可能會提出一種改進方法:在「try」塊中嘗試儘可能少的行,併爲未發生異常時應該發生的情況添加「else」塊。這可以減少代碼重複,更重要的是,可以告訴讀者你的意圖是什麼。這是一個很好的SO問題,解釋try/except/else以及爲什麼你可以使用它:http://stackoverflow.com/questions/16138232/is-it-a-good-practice-to-use-try-except-else -in-python –

回答

0

我想你會發現這個「開放性」,通過檢查你的物品是否在字典中。像這樣將工作:

my_item in lexicon 

這如果字典lexicon包含my_item的關鍵,否則爲false返回True。

但有一個更好的方法來做到這一點。

這是一個很好的機會來練習Python的「更好地要求寬恕而不是權限」的概念。怎麼樣這樣的事情:

try: 
    value = lexicon[my_item] 
except KeyError: 
    # KeyError is thrown when you index into a dictionary with a nonexistent key 
    value = 'error' 

巧合的是,你可以做同樣的事情來檢查一個字符串是否可以轉換爲一個整數。

try: 
    value = int(maybe_a_number) 
except ValueError: 
    # maybe_a_number wasn't a number! 

這是Python中的常見模式 - 嘗試以某種方式使用變量,並處理失敗的情況。

有關詞典更多的材料,請上網:http://docs.python.org/2/library/stdtypes.html#mapping-types-dict

+0

在這種情況下使用默認值會好得多; 'value = lexicon.get(my_item,「error」)' – Daenyth

+0

@Daenyth怎麼樣? – sivanes

4

您可以使用字典的與可選的默認參數get方法:

d = {"a":'letter', 4:'number'} 
result = d.get("not in d", 'error') 
print result 
# error 

這也是常見的蟒蛇使用try /除循環檢查重點錯誤,儘管這種情況可能是矯枉過正的。

d = {"a":'letter', 4:'number'} 
try: 
    result = d['not in d'] 
except KeyError: 
    result = 'error' 
print result 
# error 

我覺得查詢的最簡單的方法,如果字符串是數在python是是使用任一浮動或INT除了塊一試內,就像上面的第二個例子。你使用哪一個取決於你是否想將數字「1.2」和「3.4e5」作爲數字。