Completed Palindrome: Approaching the Problem
判断所给的一个字符串是否是回文
def is_palindrome(s): """ (str) -> bool Return True if and only if s is a palindrome. >>> is_palindrome('noon') True >>> is_palindrome('racecar') True >>> is_palindrome('dented') False """ return reverse(s) == sdef reverse(s): """ (str) -> str Return a reversed version of s. >>> reverse('hello') 'olleh' >>> reverse('a') 'a' """ rev = '' # For each character in s, add that char to the beginning of rev. for ch in s: rev = ch + rev return rev
def is_palindrome_v2(s): """ (str) -> bool Return True if and only if s is a palindrome. >>> is_palindrome_v2('noon') True >>> is_palindrome_v2('racecar') True >>> is_palindrome_v2('dented') False """ # the number of chars in s n = len(s) # Compare the first half of s to the reverse of the second half. return s[: n//2 ] == reverse( s[ n - n//2 :] )def reverse(s): """ (str) -> str Return a reversed version of s. >>> reverse('hello') 'olleh' >>> reverse('a"0 'a' """ rev = '' #For each character in s, add that char to the beginning of rev. for ch in s: rev = ch + rev return rev
def is_palindrome_v3(s): """ (str) -> bool Return True if and only if s is a palindrome. >>> is_palindrome_v3('noon') True >>> is_palindrome_v3('racecar') True >>> is_palindrome_v3('dented') False """ i = 0 j = len(s)-1 while i
The Restaurant Recommendations Problem
The Problem: Write a function that has three parameters:
- a restarurant file opened for reading - the price range ( one of $,$$,$$$,$$$$ ) - a list of cuisines. It returns a list of restaurants ( in that price range serving at least one of those cuisines ) and their ratings sorted from highest to lowest问题: 编写一个传入三个参数的函数
- 一个餐馆 - 一个价格($,$$,$$$,$$$$)美元符号越多说明消费越贵 - 一个美食列表( 注意是 list 哦 ) 函数返回一个餐馆列表,其中的每一家餐馆都满足消费价格,并且至少提供美食列表中的一种食物。并且按照受欢迎程度降序排列。"""A restaurant recommendation system.Here are some example dictionaries.These correspond to the information in restaurants_small.txt.Restaurant name to rating:# dict of {str: int}{'Georgie Porgie': 87, 'Queen St. Cafe': 82, 'Dumplings R Us': 71, 'Mexican Grill': 85, 'Deep Fried Everything': 52}Price to list of restaurant names:# dict of {str, list of str}{'$': ['Queen St. Cafe', 'Dumplings R Us', 'Deep Fried Everything'], '$$': ['Mexican Grill'], '$$$': ['Georgie Porgie'], '$$$$': []}Cuisine to list of restaurant names:# dict of {str, list of str}{'Canadian': ['Georgie Porgie'], 'Pub Food': ['Georgie Porgie', 'Deep Fried Everything'], 'Malaysian': ['Queen St. Cafe'], 'Thai': ['Queen St. Cafe'], 'Chinese': ['Dumplings R Us'], 'Mexican': ['Mexican Grill']}With this data, for a price of '$' and cuisines of ['Chinese', 'Thai'], wewould produce this list: [[82, 'Queen St. Cafe'], [71, 'Dumplings R Us']]"""# The file containing the restaurant data.FILENAME = 'c:/restaurants.txt'def recommend(file, price, cuisines_list): """(file open for reading, str, list of str) -> list of [int, str] list Find restaurants in file that are priced according to price and that are tagged with any of the items in cuisines_list. Return a list of lists of the form [rating%, restaurant name], sorted by rating%. """ # Read the file and build the data structures. name_to_rating , price_to_names , cuisine_to_names = read_restaurants(FILENAME); # Look for price or cuisines first # Price: look up the list of restaurant names for the requested price names_maching = price_to_names[price] # Now we have a list of restaurants in the right price range. # Need a new list of restaurants that serve one of the cuisines. names_final = filter_by_cuisine( names_maching , cuisine_to_names , cuisines_list ); # Now we have a list of restaurants that are the right price and serve the requested cuisine. # Need to look at ratings and sort this list. result = build_rating_list( name_to_rating , names_final ) # We're done ! Return that sorted list. print( result ) def read_restaurants(file): """ (file) -> ( dict , dict , dict ) Return a tuple of three dictionaries based on information in the file: - a dict of { restaurant name: rating% } - a dict of { price: list of restaurant names } - a dict of { cuisine: list of restaurant names } """ name_to_rating = {} price_to_names = { '$': [] , '$$': [] , '$$$': [] , '$$$$': [] } cuisine_to_names = {} fobj = open(file) lines = fobj.readlines() for i in range(0,len(lines),5): restaurant_name = lines[i].replace('\n','') rating = int( lines[i+1].replace('%','').replace('\n','') ) price = lines[i+2].replace('\n','') cuisines = lines[i+3].replace('\n','').split(',') # build name_to_rating dic name_to_rating[restaurant_name] = rating # build price_to_names dic price_to_names[price].append(restaurant_name); # build cuisine_to_names dic for c in cuisines: if not(c in cuisine_to_names): cuisine_to_names[c] = [] cuisine_to_names[c].append(restaurant_name) return ( name_to_rating , price_to_names , cuisine_to_names )def filter_by_cuisine( names_matching , cuisine_to_names , cuisines_list ): """ (list of str, dict of {str: list of str}, list of str) -> list of str >>> names = ['Queen St. Cafe', 'Dumplings R Us', 'Deep Fried Everything'] >>> cuis = 'Canadian': ['Georgie Porgie'], 'Pub Food': ['Georgie Porgie', 'Deep Fried Everything'], 'Malaysian': ['Queen St. Cafe'], 'Thai': ['Queen St. Cafe'], 'Chinese': ['Dumplings R Us'], 'Mexican': ['Mexican Grill']} >>> cuisines = ['Chinese', 'Thai'] >>> filter_by_cuisine(names, cuis, cuisines) ['Queen St. Cafe', 'Dumplings R Us'] """ names_final = []; for c in cuisines_list: for n in names_matching: if n in cuisine_to_names[c] and not( n in names_final ): names_final.append(n) return names_finaldef build_rating_list(name_to_rating, names_final): """ (dict of {str: int}, list of str) -> list of list of [int, str] Return a list of [rating%, restaurant name], sorted by rating% >>> name_to_rating = {'Georgie Porgie': 87, 'Queen St. Cafe': 82, 'Dumplings R Us': 71, 'Mexican Grill': 85, 'Deep Fried Everything': 52} >>> names = ['Queen St. Cafe', 'Dumplings R Us'] [[82, 'Queen St. Cafe'], [71, 'Dumplings R Us']] """ result = [] for n in names_final: result.append([ name_to_rating[n] , n ]) result.sort() result.reverse() return result
Testing Automatically using doctest
doctest用于检查一个模块的文档字符串的描述是否正确
def collect_vowels(s): ''' (str) -> str Return the vowels (a,e,i,o and u) from s. >>> collect_vowels('Happy Anniversary!') 'aAiea' >>> collect_vowels('xyz') '' ''' vowels = '' for char in s: if char in 'aeiouAEIOU': vowels = vowels + char return vowelsdef count_vowels(s): ''' (str) -> int Return the number of vowels in s. >>> count_vowels('Happy Anniversary!') 5 >>> count_vowels('xyz') 0 ''' num_vowels = 0 for char in s: if char in 'aeiouAEIOU': num_vowels = num_vowels + 1 return num_vowelsimport doctestdoctest.testmod()
Writing a "__main__" program
当编写一个模块,其中有一段代码只想让直接调用该模块时执行。而当其他模块import这个模块的时候不执行,可以这样做:
palindrome_v1.py
def is_palindrome_v1(s): """ (str) -> bool Return True if and only if s is a palindrome. >>> is_palindrome('noon') True >>> is_palindrome('racecar') True >>> is_palindrome('dented') False """ return reverse(s) == s def reverse(s): """ (str) -> str Return a reversed version of s. >>> reverse('hello') 'olleh' >>> reverse('a') 'a' """ rev = '' # For each character in s, add that char to the beginning of rev. for ch in s: rev = ch + rev return revprint ( "This is palindrome v1, the module name is ", __name__ )if __name__ == '__main__': # 判断是否是被其他模块import word = input("Enter a world: ") if is_palindrome_v1(word): print(word, 'is a palindrome.') else: print(word, 'is not a palindrome.')
palindrome_v2
def is_palindrome_v2(s): """ (str) -> bool Return True if and only if s is a palindrome. >>> is_palindrome_v2('noon') True >>> is_palindrome_v2('racecar') True >>> is_palindrome_v2('dented') False """ # the number of chars in s n = len(s) # Compare the first half of s to the reverse of the second half. return s[: n//2 ] == reverse( s[ n - n//2 :] )import palindrome_v1
Creating your own types
class WordplayStr(str): """A string that can report whether it has interesting properties""" def same_start_and_end(self): """ (WordplayStr) -> bool Precondition: len(self) > 0 Return whether self starts and ends with the same letter. >>> s = WordplayStr('abcba') >>> s.same_start_and_end() True >>> s = WordplayStr('cace') >>> s.same_start_and_end() False """ return self[0] == self[-1]if __name__ == '__main__': import doctest doctest.testmod()
Testing Automatically Using unittest
divisors.py
def get_divisors(num, possible_divisors): ''' (int, list of int) -> list of int Return a list of the values from possible_divisors that are divisors of num. >>> get_divisors(8, [1,2,3]) [1, 2] >>> get_divisors(4, [-2,0,2]) [-2, 2] ''' divisors = [] for item in possible_divisors: if item !=0 and num % item == 0: divisors.append(item) return divisorsif __name__ == '__main__': import doctest doctest.testmod()
unittest_example.py
import unittestimport divisorsclass TestDivisors(unittest.TestCase): """ Example unittest test mehtods for get_divisors.""" def test_divisors_example_1(self): """ Test get_divisros with 8 and [1,2,3].""" actual = divisors.get_divisors(8, [1,2,3]) expected = [1, 2] self.assertEqual( actual, expected) def test_divisors_example_2(self): """ Test get_divisros with 4 and [-2,0,2].""" actual = divisors.get_divisors(4, [-2,0,2]) expected = [-2, 2] self.assertEqual( actual, expected)if __name__ == '__main__': unittest.main(exit=False)
Another Unittest Example
duplicates.py
def remove_shared(L1,L2): """ (list list) Remove items from L1 that are in both L1 and L2. >>> list_1 = [1,2,3,4,5,6] >>> list_2 = [2,4,5,7] >>> remove_shared(list_1,list_2) >>> list_1 [1, 3, 6] >>> list_2 [2, 4, 5, 7] """ for v in L2: if v in L1: L1.remove(v) if __name__ == '__main__': import doctest doctest.testmod()
test_duplicates.py
import unittestimport duplicatesclass TestRemoveShared(unittest.TestCase): """Tests for function duplicates.remove_shared.""" def test_general_case(self): """ Test remove_shared where there are items that appear in both lists, and items that appear in only one or the other list. """ list_1 = [1,2,3,4,5,6] list_2 = [2,4,5,7] list_1_expected = [1,3,6] list_2_expected = [2,4,5,7] duplicates.remove_shared(list_1,list_2) self.assertEqual(list_1,list_1_expected) self.assertEqual(list_2,list_2_expected)if __name__ == '__main__': unittest.main(exit=False)