سؤال

I am working on the exercise 48 of Learn Python The Hard Way and writing the lexicon dictionary and the scan module to run the following test on:

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')])

I have most of this figured out, except the numbers and errors tests. When the user input is a word not defined in the dictionary, it needs to be tagged with the error value name, and if it's a number - the number value name. Obviously, I can preemptively add all the inputs that will be tested into the dictionary, but that's cheating.

my dictionary looks like this:

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

Is there a way to work, uh, "open-ended" definitions for numbers and undefined words into this?

UPDATE. Here is a working solution :

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

I think you'll find this "open-endedness" by checking whether your item is in the dictionary. Something like this will work:

my_item in lexicon

This returns True if the dictionary lexicon contains a key of my_item, and False otherwise.

But there is a better way to do it.

This is a good opportunity to practice Python's concept of "It's Better To Ask Forgiveness Than Permission". How about something like:

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

Coincidentally, you can do the same sort of thing to check whether a string can be converted to an integer.

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

This is a common pattern in Python -- try to use a variable in a certain way, and handle the failure case.

For more material on dictionaries, check out: http://docs.python.org/2/library/stdtypes.html#mapping-types-dict

نصائح أخرى

You can use the get method of the dictionary with the optional default argument:

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

It's also common in python to use try/except loops to check for key errors, though it's probably overkill for this case.

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

I think the easiest way to check if a string is a number in python is is to use either float or int inside a try except block, much like the second example above. Which one you use will depend on whether you want to consider "1.2" and "3.4e5" as numbers or not.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top