“开放式”字典键? (LPTHW练习48相关)

时间:2014-02-10 19:14:55

标签: python dictionary nosetests

我正在练习学习Python The Hard Way的练习48,并编写lexicon字典和scan模块来运行以下测试:

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...
}

有没有办法工作,呃,数字和未定义的单词的“开放式”定义到这个?

更新。这是一个有效的解决方案:

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

2 个答案:

答案 0 :(得分:4)

您可以使用带有可选默认参数的字典的get方法:

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

在python中使用try / except循环来检查关键错误也很常见,尽管这种情况可能有点过分。

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

我认为检查字符串是否是python中的数字的最简单方法是在try except块中使用float或int,就像上面的第二个例子一样。您使用哪一个取决于您是否要将“1.2”和“3.4e5”视为数字。

答案 1 :(得分:0)

我认为你会通过检查你的项目是否在字典中来找到这种“开放性”。这样的事情会起作用:

my_item in lexicon

如果字典lexicon包含my_item的键,则返回True,否则返回False。

但是有一种更好的方法可以做到。

这是练习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