跳转到内容

Think Python/答案

来自 Wikibooks,开放世界中的开放书籍

第 1 章

[编辑 | 编辑源代码]

请参阅下面的第 1 章练习。

练习 1.2

[编辑 | 编辑源代码]

1.) 42 分 42 秒有多少秒?

>>> (42 * 60) + 42

2562 秒


2.) 10 公里有多少英里?提示:1 英里约等于 1.61 公里。

>>> 10/1.61

6.21 英里


3.) 如果你在 42 分 42 秒内跑完 10 公里,你的平均每英里时间是多少?你的平均速度是多少英里每小时?(提示:1 英里约等于 1.61 公里。)

>>> 10 / 1.61 # 将公里转换为英里

6.211180124223602

>>> (42 * 60) + 42 # 将时间转换为秒

2562


>>> 2562 / 6.211180124223602 # 你的平均每英里时间(秒)

412.482

>>> 412.482 / 60 # 你的平均每英里时间(分钟)

6.874700000000001


>>> 60 / 6.874700000000001 # 英里每小时

8.727653570337614


另一种方法

>>> 10 / 42.7 # 平均每分钟公里

0.23419203747072598

>>> 0.23419203747072598 * 60 # 公里每小时

14.05152224824356

>>> 14.05152224824356 / 1.61 # 转换为英里每小时

8.727653570337614

或者一个一行代码

>>> (10 / 1.61) / (42.7 / 60) # (距离,英里) / (时间,小时)

8.727653570337614 # 英里/小时

第 2 章

[编辑 | 编辑源代码]

练习 2.1

[编辑 | 编辑源代码]

如果你输入一个以 0 开头的整数,你可能会得到一个令人困惑的错误

>>> zipcode = 02492
                  ^
SyntaxError: invalid token

其他数字似乎可以工作,但结果很奇怪

>>> zipcode = 02132
>>> print zipcode
1114

因此,python 假设你想要将八进制数转换为十进制数。在以 8 为底的数字系统中,有效的数字是 0、1、2、3、4、5、6 和 7

Base  8: 00 01 02 03 04 05 06 07 10 11 12 13 14 15 16 17 20 21 22 23 24
Base 10: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20

每 8 个数字,我们将左侧列加 1。这意味着最右侧的列是“1”的数量。它左侧的是“8”的数量,它旁边的列是“8”列乘以“8”列的完整列,即 64。它旁边的列是 64*8 - 512 等等。有关更多信息,请阅读 八进制数学

这就是为什么 zipcode = 02492 无效的原因,因为数字 9 不是有效的八进制数。我们可以手动进行转换,如下所示

>>> print 02132
1114
>>> (2*512)+(1*64)+(3*8)+(2*1)
1114
>>>

练习 2.2

[编辑 | 编辑源代码]

半径为 的球体的体积是 4/3 π 。半径为 5 的球体的体积是多少?

>>> pi = 3.1415926535897932
>>> r = 5
>>> 4/3*pi*r**3 # This is the wrong answer
392.69908169872411
>>> r = 5.0 # Radius can be a float here as well, but is not _necessary_.
>>> 4.0/3.0*pi*r**3 # Using floats give the correct answer
523.5987755982989
>>>

假设一本书的封面价为 24.95 美元,但书店可以享受 40% 的折扣。第一本的运费为 3 美元,每增加一本运费为 75 美分。60 本书的总批发价是多少?

 $24.95  Cost
  $9.98  Discount per book
 $14.97  Cost per book after discount
  60     Total number of books
$898.20  Total cost not inc delivery

  $3.00  First book delivery
  59     Remaining books
  $0.75  Delivery cost for extra books
 $44.25  Total cost for extra books
 $47.25  Total Delivery cost
	
$945.45	 Total Bill

This answer is wrong because 40.0/100.0 return wrong value 0.40000000000000002 for more info see IEEE 754 (Standard for Floating-Point Arithmetic)
>>> (24.95-24.95*40.0/100.0)*60+3+0.75*(60-1)
945.44999999999993
>>> 24.95*0.6*60+0.75*(60-1)+3
945.45

You can use the decimal module to maintain precision.
from decimal import Decimal
..
...
def wholesale_cost(args):

    d = 1 - args.get('discount')/100 
    purchase = Decimal(args.get('cost') * d * 60)
    return purchase + Decimal(args.get('delivery'))

args =  {'cost': 24.95, 'discount': 40, 'delivery': 3.00+0.75*59}

另一个使用函数和输入提示的解决方案

# Total wholesale book cost calculator
cover_price = 24.95

number_of_books = int(input("How many books do you want to order at wholesale? "))

def ship_cost (number_of_books):
    if number_of_books == 1:
        return (number_of_books * 3) # Cost of shipping one book is $3
    else:
        return (3 + (number_of_books - 1) * 0.75) # Each additional copy of the book is $0.75 to ship

def discounted_price(number_of_books):
    return(cover_price - (cover_price * .4)) # There is a 40% discount on wholesale book sales

def wholesale_cost(number_of_books):
    return ((discounted_price(number_of_books) * number_of_books) + ship_cost(number_of_books))

print("The cost of buying and shipping", number_of_books, "books is $",round(wholesale_cost(number_of_books), 2))

如果我早上 6:52 离开家,以轻松的步伐跑 1 英里(每英里 8:15),然后以快步跑 3 英里(每英里 7:12),最后再以轻松的步伐跑 1 英里,我几点回家吃早餐?

答案:早上 7:30

我的做法

>>> start = (6*60+52)*60
>>> easy = (8*60+15)*2
>>> fast = (7*60+12)*3
>>> finish_hour = (start + easy + fast)/(60*60.0)
>>> finish_floored = (start + easy + fast)//(60*60)  #int() function can also be used to get integer value, but it hasn't taught yet.
>>> finish_minute  = (finish_hour - finish_floored)*60
>>> print ('Finish time was %d:%d' % (finish_hour,finish_minute))
Finish time was 7:30

*** ANOTHER WAY ***
start_time_hr = 6 + 52 / 60.0
easy_pace_hr = (8 + 15 / 60.0 ) / 60.0
tempo_pace_hr = (7 + 12 / 60.0) / 60.0
running_time_hr = 2 * easy_pace_hr + 3 * tempo_pace_hr
breakfast_hr = start_time_hr + running_time_hr
breakfast_min = (breakfast_hr-int(breakfast_hr))*60
breakfast_sec= (breakfast_min-int(breakfast_min))*60

print ('breakfast_hr', int(breakfast_hr) )
print ('breakfast_min', int (breakfast_min) )
print ('breakfast_sec', int (breakfast_sec) )
>>>

第 3 章

[编辑 | 编辑源代码]

练习 3.1

[编辑 | 编辑源代码]

Python 提供了一个名为 len 的内置函数,它返回字符串的长度,因此 len('allen') 的值为 5。编写一个名为 right_justify 的函数,它接受一个名为 s 的字符串作为参数,并打印该字符串,并在其前面加上足够的空格,以便字符串的最后一个字母出现在显示的第 70 列。

>>> def right_justify(s):
     print (' '*(70-len(s))+s)
 
>>> right_justify('allen')
                                                                 allen
>>>



使用串联和重复的另一种解决方案

def right_justify(s):
    total_length = 70
    current_length = len(s)
    current_string = s
    while current_length < total_length:
       current_string = " " + current_string
       current_length = len(current_string)
    print(current_string)

OUTPUT

>>> right_justify("monty")
                                                                 monty

练习 3.3

[编辑 | 编辑源代码]

你可以在 http://thinkpython.com/code/grid.py 中看到我的解决方案。

"""
Solution to Exercise 3.5 on page 27 of Think Python
Allen B. Downey, Version 1.1.24+Kart [Python 3.2]

"""

# here is a mostly-straightforward solution to the
# two-by-two version of the grid.

def do_twice(f):
    f()
    f()

def do_four(f):
    do_twice(f)
    do_twice(f)

def print_beam():
    print('+ - - - -', end='')

def print_post():
    print('|        ', end='')

def print_beams():
    do_twice(print_beam)
    print('+')

def print_posts():
    do_twice(print_post)
    print('|')

def print_row():
    print_beams()
    do_twice(print_posts)

def print_grid():
    do_twice(print_row)
    print_beams()

print_grid()
 ____________   

# another solution

def do_twice(f):
    f()
    f()

def do_four(f):
    do_twice(f)
    do_twice(f)

def print_column():
    print '+----+----+'

def print_row():
    print '|    |    |'

def print_rows():
    do_four(print_row)

def do_block():
    print_column()
    print_rows()

def print_block():
    do_twice(do_block)
    print_column()

print_block()

# nathan moses-gonzales
_________

# straight-forward solution to 4x4 grid

def do_twice(f):
    f()
    f()

def do_four(f): # not needed for 2x2 grid
    do_twice(f)
    do_twice(f)

def print_beam():
    print('+----', end='')

def print_post():
    print('|    ', end='')

def print_beams():
    do_twice(print_beam)
    print('+')

def print_posts():
    do_twice(print_post)
    print('|')

def print_row():
    print_beams()
    do_twice(print_posts)

def print_grid2x2():
    do_twice(print_row)
    print_beams()

def print_beam4():
    do_four(print_beam)
    print('+')

def print_post4():
    do_four(print_post)
    print('|')

def print_row4():
    print_beam4()
    do_twice(print_post4)

def print_grid4x4():
    do_four(print_row4)
    print_beam4()

print_grid4x4()
-----------------------

# here is a less-straightforward solution to the
# four-by-four grid 

def one_four_one(f, g, h):
    f()
    do_four(g)
    h()

def print_plus():
    print '+',

def print_dash():
    print '-',

def print_bar():
    print '|',

def print_space():
    print ' ',

def print_end():
    print

def nothing():
    "do nothing"

def print1beam():
    one_four_one(nothing, print_dash, print_plus)

def print1post():
    one_four_one(nothing, print_space, print_bar)

def print4beams():
    one_four_one(print_plus, print1beam, print_end)

def print4posts():
    one_four_one(print_bar, print1post, print_end)

def print_row():
    one_four_one(nothing, print4posts, print4beams)

def print_grid():
    one_four_one(print4beams, print_row, nothing)

print_grid()

comment = """
After writing a draft of the 4x4 grid, I noticed that many of the
functions had the same structure: they would do something, do
something else four times, and then do something else once.

So I wrote one_four_one, which takes three functions as arguments; it
calls the first one once, then uses do_four to call the second one
four times, then calls the third.

Then I rewrote print1beam, print1post, print4beams, print4posts,
print_row and print_grid using one_four_one.

Programming is an exploratory process.  Writing a draft of a program
often gives you insight into the problem, which might lead you to
rewrite the code to reflect the structure of the solution.

--- Allen
"""

print comment

# another solution
def beam():
    plus = "+"
    minus = "-"*4
    print(plus, minus, plus,minus, plus, minus, plus, minus, plus)

def straight():
    straight = "|"
    space = " "*4
    print(straight, space, straight, space, straight, space, straight, space,
          straight, space)

def quad_straight():
    straight()
    straight()
    straight()
    straight()

def twice():
    beam()
    quad_straight()
    beam()
    quad_straight()

def quad():
    twice()
    twice()
    beam()

quad()
-- :)
------------------

# Without functions. 
print("+ - - - - " * 2 + "+")
print("|\t\t  | \t\t|\n" * 3 + "|\t\t  | \t\t|")
print("+ - - - - " * 2 + "+")
print("|\t\t  | \t\t|\n " *3 + "|\t\t  | \t\t|")
print("+ - - - - " * 2 + "+")

------------------

Why not using the first solution and adapt it to the number of rows

def do_twice(f):
    f()
    f()

def do_four(f):
    do_twice(f)
    do_twice(f)

def print_column():
    print '+----+----+----+----+'

def print_row():
    print '|    |    |    |    |'

def print_rows():
    do_four(print_row)

def do_block():
    print_column()
    print_rows()

def print_block():
    do_twice(do_block)
    # print_column()
    do_twice(do_block)
    print_column()

print_block()


-----------------------
# mteodor

def draw_line(bar, middle = ' ', repeat = 2, length = 2):
  """ Draw a single line like this:
  [ (B M*repeat)*length B]
  """
  for k in range(length):
    print("%s %s " % (bar, middle*repeat), end='')
  print(bar)

def draw_grid(length = 2, height = 2, width = 2):
  """ Draw a grid like this:
  + -- + -- +
  |    |    |
  |    |    |
  + -- + -- +
  |    |    |
  |    |    |
  + -- + -- +
  where:
  * length x height are the table size
  * width is the size of a cell/column
  """
  for i in range(height):
    draw_line('+', '-', width, length)
    for j in range(length):
      draw_line('|', ' ', width, length)
  draw_line('+', '-', width, length)

draw_grid(4, 4, 3)


--------------------------
#kipp

# auto adjust size of columns

size=4

def beam():
    print(" + - - - -"*size, "+")

def post():
    print(" |        "*size, "|")

def repeat(func):
    func()
    func()
    func()

# manual adjust size for rows
# this is 4

beam()
repeat(post)
beam()
repeat(post)
beam()
repeat(post)
beam()
repeat(post)
beam()

第 4 章

[编辑 | 编辑源代码]

4.3 练习 1

[编辑 | 编辑源代码]
from TurtleWorld import *

world = TurtleWorld()
bob = Turtle()

def square(t):
    for i in range(4):
        fd(t, 100)
        lt(t)

square(bob)
wait_for_user()

4.3 练习 2

[编辑 | 编辑源代码]
from TurtleWorld import *

world = TurtleWorld()
bob = Turtle()
print(bob)

def square(t, length):
    t = Turtle()
    for i in range(4):
        fd(t, length)
        lt(t)

square(bob, 200)
wait_for_user()

4.3 练习 3

[编辑 | 编辑源代码]
from swampy.TurtleWorld import *

world = TurtleWorld()
bob = Turtle()
print(bob)

def polygon(t, length, n):
    
    for i in range(n):
        fd(t, length)
        lt(t, 360 / n)

polygon(bob, 50, 8)
wait_for_user()

第 5 章

[编辑 | 编辑源代码]

练习 5.2

[编辑 | 编辑源代码]
def countdown(a):         # A typical countdown function
    if a < 0:
        print("Blastoff")
    elif a > 0:
        print(a)
        countdown(a - 1)

def call_function(n,a):    # The countdown function is called "n" number of times. Any other function can be used instead of countdown function.
    for i in range(n):
        countdown(a)
    
call_function(3, 10)

练习 5.3

[编辑 | 编辑源代码]
def is_triangle(a, b, c):
       if a <= b+c:
            if b <= a+c:
                 if c <= a+b:
                    return 'yes'
                 else:
                    return 'no'
            else:
                 return 'no'
       else:
            return 'no'

is_triangle(1, 12, 1)
'no'

练习 5.3

[编辑 | 编辑源代码]
def is_triangle(a, b, c):
       if a<=b+c and b<=a+c and c<=a+b:
           return 'yes'
       else:
           return 'no'

is_triangle(1, 12, 3)
'no'

第 9 章

[编辑 | 编辑源代码]

练习 9.1

[编辑 | 编辑源代码]
fin = open('words.txt')
for line in fin:
	word = line.strip()
	if len(word) > 20:
		print (word)

练习 9.2

[编辑 | 编辑源代码]
fin = open('words.txt')

def has_no_e(word):
    for char in word:
        if char in 'Ee':
            return False
    return True  

count = 0
for line in fin:
    word = line.strip()
    if has_no_e(word):
        count += 1
        print (word)

percent = (count / 113809.0) * 100

print (str(percent)) + "% of the words don't have an 'e'."

练习 9.3

[编辑 | 编辑源代码]
fin = open('words.txt')

def avoids(word,letter):
    for char in word:
        if char in letter:
            return False
    return True


letter = raw_input('What letters to exclude? ')
count = 0
for line in fin:
    word = line.strip()
    if avoids(word, letter):
        count += 1
        print word

percent = (count / 113809.0) * 100

print str(percent) + "% of the words don't have " + letter + '.'

练习 9.4

[编辑 | 编辑源代码]
def uses_only(word, letters):
    """returns true if word is made only out of letters  else flase"""
    for letter in word:
        if letter not in letters:
            return False
    return True

第 10 章

[编辑 | 编辑源代码]

练习 10.1

[编辑 | 编辑源代码]

编写一个名为 nested_sum 的函数,它接收一个嵌套的整数列表,并累加所有嵌套列表中的元素。

def nested_sum(nestedList):
        '''
        nestedList: list composed of nested lists containing int.
        Returns the sum of all the int in the nested list
        '''
        newList = []
        #Helper function to flatten the list
        def flatlist(nestedList):
                '''
                Returns a flat list
                '''
                for i in range(len(nestedList)):
                        if type(nestedList[i]) == int:
                                newList.append(nestedList[i])
                        else:
                                flatlist(nestedList[i])
                return newList

        flatlist(nestedList)
        print sum(newList)
        
nested_sum(nestedList)

练习 10.2

[编辑 | 编辑源代码]

编写一个名为 "capitalize_nested" 的函数,它接收一个嵌套的字符串列表,并返回一个新的嵌套列表,其中所有字符串都已大写。

>>> def capitalize_nested(l): 
        def capitalize(s):
            return s.capitalize()
        for n, i in enumerate(l):       
            if type(i) is list:
                l[n] = capitalize_nested(l[n])
            elif type(i) is str:
                l[n] = capitalize(i)
        return l

练习 10.3

[编辑 | 编辑源代码]

编写一个函数,它接收一个数字列表,并返回累加和。

>>> def cumulative(l):
    cumulative_sum = 0
    new_list = []
    for i in l:
        cumulative_sum += i
        new_list.append(cumulative_sum)
    return new_list

练习 10.4

[编辑 | 编辑源代码]

编写一个名为 middle 的函数,它接收一个列表,并返回一个包含除第一个和最后一个元素之外的所有元素的新列表。

>>> def middle(x):
	res = []
	i = 1
	while i <= len(x)-2:
		res.append(x[i])
		i += 1
	return res

这也可以通过简单地使用切片来实现。

>>> def middle(x):
        return x[1:-1]

练习 10.5

[编辑 | 编辑源代码]

编写一个名为 chop 的函数,它接收一个列表并修改它,删除第一个和最后一个元素,并返回 None。

>>> def chop(x):
		del x[:1]
		del x[-1:]

第 11 章

[编辑 | 编辑源代码]

练习 11.1

[编辑 | 编辑源代码]

编写一个函数,它读取 words.txt 中的单词并将它们存储为字典中的键。值并不重要。然后,可以使用 in 运算符作为快速方法来检查字符串是否在字典中。

fin = open('words.txt')
englishdict = dict()


def create_diction():
    counter = 0
    dictionairy = dict()
    for line in fin:
        word = line.strip()
        dictionairy[word] = counter
        counter += 1
    return dictionairy

练习 11.2

[编辑 | 编辑源代码]
def invert_dict(s):
    i={}
    for key in s:
        v=s[key]
        i.setdefault(v, []).append(key)
    return i

编辑: 这不是我在 "Think Python" 的版本中找到的练习,所以为了以防万一其他人好奇,我添加了我的答案: 使用 get 更简洁地编写 histogram。你应该能够消除 if 语句。

def histogram(s):
	d = dict()
	for c in s:
		d[c] = d.get(c,0)+1
	return d

练习 11.3

[编辑 | 编辑源代码]

字典有一个名为 keys 的方法,它返回字典的键,无特定顺序,作为列表。修改 print_hist 以按字母顺序打印键及其值。

v = {'p' : 1, 'a' : 1, 'r' : 2, 'o' : 1, 't' : 1}
def print_hist(h):
    d = []
    d += sorted(h.keys())
    for c in d:
        print(c, h[c])

或者

v = {'p' : 1, 'a' : 1, 'r' : 2, 'o' : 1, 't' : 1}
def print_hist(h):
    for c in sorted(h.keys()):
        print c, h[c]

练习 11.4

[编辑 | 编辑源代码]

修改 reverse_lookup,使其构建并返回映射到 v 的所有键的列表,如果没有则返回空列表。

def reverse_lookup(d,v):
    l = list()
    for c in d:
        if d[c] == v:
            l.append(c)
    return l

第 12 章

[编辑 | 编辑源代码]

练习 12.1

[编辑 | 编辑源代码]
numbers = (1,2,3)
def sumall(numbers):
    x = 0
    for i in numbers:
        x = x + i
    print x
sumall(numbers)

或者

def sumall(*t):
    x = 0
    for i in range(len(t)):
        x += t[i]
    return x

或者

def sumall(*args):
	t = list(args)
	return sum(t)

或者

def sumall(*args):
    return sum(args)

练习 12.2

[编辑 | 编辑源代码]
import random

def sort_by_length(words):
	t = []
	for word in words:
		t.append((len(word),word))
	t.sort(reverse=True)
	res = []
	for length, word in t:
		res.append(word)
	i=0
	final = []
	while i <= len(res)-2:
		if len(res[i]) == len(res[i+1]):
			y_list = [res[i], res[i+1]]
			random.shuffle(y_list)
			final = final + y_list
			i += 2
		else:
			final.append(res[i])
			i += 1
	if i == len(res)-1:
		final.append(res[i])
	return final

或者

from random import shuffle

def sort_by_length(words):
	r = []
	d = dict()
	for word in words:
		d.setdefault(len(word), []).append(word)
	for key in sorted(d, reverse=True):
		if len(d[key]) > 1:
			shuffle(d[key])
		r.extend(d[key])
	return r

练习 12.3

[编辑 | 编辑源代码]
import string

def most_frequent(s):
	d = dict()
	inv = dict()
	for char in s:
		if char in string.ascii_letters:
			letter = char.lower()		
			d[letter] = d.get(letter, 0) + 1
			
	for letter, freq in d.items():
		inv.setdefault(freq, []).append(letter)
		
	for freq in sorted(inv, reverse=True):
		print('{:.2%}:'.format(freq/(sum(list(inv)*len(inv[freq])))), ', '.join(inv[freq]))

第 13 章

[编辑 | 编辑源代码]

练习 13.7

[编辑 | 编辑源代码]
from string import punctuation, whitespace, digits
from random import randint
from bisect import bisect_left

def process_file(filename):
	h = dict()
	fp = open(filename)
	for line in fp:
		process_line(line, h)
	return h

def process_line(line, h):
	line = line.replace('-', ' ')
	for word in line.split():
		word = word.strip(punctuation + whitespace + digits)
		word = word.lower()
		if word != '':
			h[word] = h.get(word, 0) + 1

hist = process_file('emma.txt')

def cum_sum(list_of_numbers):
	cum_list = []
	for i, elem in enumerate(list_of_numbers):
		if i == 0:
			cum_list.append(elem)
		else:
			cum_list.append(cum_list[i-1] + elem)
	return cum_list

def random_word(h):
	word_list = list(h.keys())
	num_list = []
	for word in word_list:
		num_list.append(h[word])
	cum_list = cum_sum(num_list)
	i = randint(1, cum_list[-1])
	pos = bisect_left(cum_list, i)
	return word_list[pos]

print(random_word(hist))

第 14 章

[编辑 | 编辑源代码]

练习 14.3

[编辑 | 编辑源代码]
import shelve

def dict_of_signatures_and_words(filename='words.txt'):
	d = dict()
	for line in open(filename):
		word = line.lower().strip()
		signature = ''.join(sorted(word))
		d.setdefault(signature, []).append(word)
	return d

def db_of_anagrams(filename='anagrams', d=dict_of_signatures_and_words()):
	db = shelve.open(filename)
	for key, values in d.items():
		if len(values)>1:
			for index, value in enumerate(values):
				db[value]=values[:index]+values[index+1:]
	db.close()

def print_contents_of_db(filename='anagrams'):
	db = shelve.open(filename, flag='r')
	for key in sorted(db):
		print(key.rjust(12), '\t<==>\t', ', '.join(db[key]))
	db.close()

db_of_anagrams()
print_contents_of_db()

练习 14.5

[编辑 | 编辑源代码]
# Replace urllib.request with urllib if you use Python 2.
# I would love to see a more elegant solution for this exercise, possibly by someone who understands html.

import urllib.request

def check(zip_code):
	if zip_code == 'done':
		return False
		
	else:
                if len(zip_code) != 5:
		      print('\nThe zip code must have five digits!')
		return True

def get_html(zip_code):
	gibberish = urllib.request.urlopen('http://www.uszip.com/zip/' + zip_code)
	less_gib = gibberish.read().decode('utf-8')
	return less_gib

def extract_truth(code, key, delimiter):
	pos = code.find(key) + len(key)
	nearly_true = code[pos:pos+40]
	truth = nearly_true.split(delimiter)[0]
	return truth

while True:
	zip_code = input('Please type a zip code (5 digits) or "done" if want to stop:\n')
	
	if not check(zip_code):
                 break
	
	code = get_html(zip_code)
	
	invalid_key = '(0 results)'
	if invalid_key in code:
		print('\nNot a valid zip code.')
		continue
	
	name_key = '<title>'
	name_del = ' zip'
	name = extract_truth(code, name_key, name_del)
	
	pop_key = 'Total population</dt><dd>'
	pop_del = '<'
	pop = extract_truth(code, pop_key, pop_del)
	
	if not 1 < len(pop) < 9:
		pop = 'not available'

	print('\n' + name)
	print('Population:', pop, '\n')

第 15 章

[编辑 | 编辑源代码]

练习 15.1

[编辑 | 编辑源代码]
import math

class Point(object):
	"""represents a point in 2-D space"""

def distance(p1, p2):
	distance = math.sqrt((p2.x - p1.x)**2 + (p2.y - p1.y)**2)
	return distance

p1 = Point()
p2 = Point()

p1.x = 3
p1.y = 2
p2.x = 4
p2.y = 3

print(distance(p1, p2))

练习 15.3

[编辑 | 编辑源代码]
import copy

def move_rectangle(rec, dx, dy):
    """ does a deep copy and return the newRec with changes applied """
    newRec = copy.deepcopy(rec)
    newRec.corner.x += dx
    newRec.corner.y += dy

    return newRec

第 16 章

[编辑 | 编辑源代码]

练习 16.1

[编辑 | 编辑源代码]
def print_time(t):
    print '%.2d:%.2d:%.2d' % (t.hour, t.minute, t.second)

或者

# Solution for Python3
# More on string formatting: https://docs.pythonlang.cn/py3k/library/string.html#formatspec

def print_time(t):
    # 0 is a fill character, 2 defines the width
    print('{}:{:02}:{:02}'.format(t.hour, t.minute, t.second))

练习 16.2

[编辑 | 编辑源代码]
def is_after(t1, t2):
    return (t1.hour, t1.minute, t1.second) > (t2.hour, t2.minute, t2.second)

练习 16.3

[编辑 | 编辑源代码]
# Comment not by the author: This will give a wrong result, if (time.second + seconds % 60) > 60

def increment(time, seconds):

    n = seconds/60
    time.second += seconds - 60.0*n
    time.minute += n

    m = time.minute/60
    time.minute -= m*60
    time.hour += m

或者

# Solution for Python3
# Replace '//' by '/' for Python2

def increment(time, seconds):
	time.second += seconds
	time.minute += time.second//60
	time.hour += time.minute//60
	
	time.second %= 60
	time.minute %= 60
	time.hour %= 24
# A different way of going about it

def increment(time, seconds):
    # Converts total to seconds, then back to a readable format
    time.second = time.hour*3600 + time.minute*60 + time.second + seconds
    (time.minute, time.second) = divmod(time_in_seconds, 60)
    (time.hour, time.minute) = divmod(time.minute, 60)

练习 16.4

[编辑 | 编辑源代码]
# Solution for Python3
# Replace '//' by '/' for Python2

from copy import deepcopy

def increment(time, seconds):
	r = deepcopy(time)
	
	r.second += seconds
	r.minute += r.second//60
	r.hour += r.minute//60
	
	r.second %= 60
	r.minute %= 60
	r.hour %= 24

	return r

练习 16.5

[编辑 | 编辑源代码]
class Time(object):
    """represents the time of day.
        attributes: hour, minute, second"""

time = Time()
time.hour = 11
time.minute = 59
time.second = 30

def time_to_int(time):
    minutes = time.hour * 60 + time.minute
    seconds = minutes * 60 + time.second
    return seconds

def int_to_time(seconds):
    time = Time()
    minutes, time.second = divmod(seconds, 60)
    time.hour, time.minute = divmod(minutes, 60)
    return time

def increment(time, addtime):
    seconds = time_to_int(time)
    return int_to_time(seconds + addtime)

def print_time (x):
    print 'The time is %.2d : %.2d : %.2d' % (x.hour, x.minute, x.second)
print_time (time)

newtime = increment (time, 70)

print_time (newtime)

练习 16.6

[编辑 | 编辑源代码]
def time_to_int(time):
	minutes = time.hour * 60 + time.minute
	seconds = minutes * 60 + time.second
	return seconds

def int_to_time(seconds):
	time = Time()
	minutes, time.second = divmod(seconds, 60)
	time.hour, time.minute = divmod(minutes, 60)
	return time

def mul_time(time, factor):
	seconds = time_to_int(time)
	seconds *= factor
	seconds = int(seconds)
	return int_to_time(seconds)
	
def average_pace(time, distance):
	return mul_time(time, 1/distance)

练习 16.7

[编辑 | 编辑源代码]

编写一个 Date 对象的类定义,该对象具有属性 daymonthyear。编写一个名为 increment_date 的函数,它接受一个 Date 对象 date 和一个整数 n,并返回一个新的 Date 对象,表示 daten 天。提示:“九月有三十天……”挑战:你的函数是否正确处理了闰年?请查看 wikipedia.org/wiki/Leap_year

class Date(object):
	"""represents a date.
	attributes: day, month, year"""

def print_date(date):
	# German date format

	print('{}.{}.{}'.format(date.day, date.month, date.year))

def is_leap_year(year):
        # http://en.wikipedia.org/wiki/Leap_year#Algorithm

	if year % 4 == 0:
		if year % 100 == 0:
			if year % 400 == 0:
				return True
			return False
		return True
	return False

def month_list(year):
	if is_leap_year(year):
		return [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
	return [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]

def days_of_year(year):
	if is_leap_year(year):
		return 366
	return 365

def date_to_int(date):
	days = 0
	for year in range(1, date.year):
		days += days_of_year(year)
	
	month_days = month_list(date.year)
	for month in range(1, date.month):
		days += month_days[month - 1]
	
	days += date.day - 1
	return days

def int_to_date(days):
	date = Date()
	
	date.year = 1
	next_days = 365
	while days >= next_days:
		date.year += 1
		days -= next_days
		next_days = days_of_year(date.year)
		
	date.month = 1
	next_days = 31
	month_days = month_list(date.year)
	while days >= next_days:
		date.month += 1
		days -= next_days
		next_days = month_days[date.month - 1]
	
	date.day = days + 1
	return date

def increment_date(date, n):
	days = date_to_int(date)
	return int_to_date(days + n)

d1 = Date()
d1.day, d1.month, d1.year = 8, 3, 2012
print_date(d1)

d2 = increment_date(d1, 7)
print_date(d2)

练习 16.8

[编辑 | 编辑源代码]

1. 使用 datetime 模块编写一个程序,获取当前日期并打印星期几。

from datetime import date

def current_weekday():
	i = date.today()
	print i.strftime('%A')

current_weekday()

2. 编写一个程序,以生日作为输入,并打印用户的年龄以及到他们下一个生日的天数、小时数、分钟数和秒数。

# Python3 solution. Replace "input" by "raw_input" for Python2.
from datetime import datetime

def time_until_birthday():
    dob_input = input(('Please enter the date of your birth in '
                       'the format "mm/dd/yyyy": '))
    dob = datetime.strptime(dob_input, '%m/%d/%Y')
    now = datetime.now()
    if now > datetime(now.year, dob.month, dob.day):
        age = now.year - dob.year
        next_year = True
    else:
        age = now.year - dob.year - 1
        next_year = False
    time_to_birthday = datetime(now.year + next_year,
                                dob.month, dob.day) - now
    days = time_to_birthday.days
    hours, remainder = divmod(time_to_birthday.seconds, 3600)
    minutes, seconds = divmod(remainder, 60)
    print("\nYou are {} years old.".format(age))
    print(("You have {0} days, {1} hours, {2} minutes and {3} "
           "seconds left until your next birthday.").format(
               days, hours, minutes, seconds))

time_until_birthday()

第 17 章

[编辑 | 编辑源代码]

练习 17.8

[编辑 | 编辑源代码]

2.

from visual import scene, sphere

scene.range = (256, 256, 256)
scene.center = (128, 128, 128)

t = range(0, 256, 51)

for x in t:
    for y in t:
        for z in t:
            pos = x, y, z
            color = (x/255., y/255., z/255.)
            sphere(pos=pos, radius=10, color=color)

3. 下载 http://thinkpython.com/code/color_list.py 并使用 read_colors 函数生成系统上可用颜色的列表,包括它们的名称和 RGB 值。对于每个命名颜色,在对应于其 RGB 值的位置绘制一个球体。

# As there currently (2013-04-12) is no function read_colors in color_list.py
# I use a workaround and simply import the variable COLORS from color_list.py.
# I then use the function all_colors() on COLORS to get a list of the colors.

from color_list import COLORS
from visual import scene, sphere

def all_colors(colors_string=COLORS):
    """Extract a list of unique RGB-tuples from COLORS.
    The tuples look like (r, g, b), where r, g and b are each integers in
    [0, 255].
    """

    # split the string into lines and remove irrelevant lines
    lines = colors_string.split('\n')[2:-2]  

    # split the individual lines and remove the names
    numbers_only = [line.split()[:3] for line in lines]
    
    # turn strings into ints and rgb-lists into tuples
    rgb_tuples = [tuple([int(s) for s in lst]) for lst in numbers_only]

    # return a list of unique tuples
    return list(set(rgb_tuples))

def make_spheres(color_tuples=all_colors()):
    scene.range = (256, 256, 256)
    scene.center = (128, 128, 128)
    for (r, g, b) in color_tuples:
        sphere(pos=(r, g, b), radius=7, color=(r/255., g/255., b/255.))

if __name__ == '__main__':
    make_spheres()

第 3.5 章

[编辑 | 编辑源代码]

计算器

[编辑 | 编辑源代码]
#recursion or recursive
print "\n	INDEX\n""\n	C=1 for addition\n""\n	C=2 for substraction\n""\n	
C=3 for multiplication\n""\n	C=4 for division\n""\n	C=5 for to find modulus\n""\n	C=6 to find factorial\n"
C=input("Enter your choice here: ")
def add(x,y):
	c=x+y
	print x,"+",y,"=",c
def sub(x,y):
	c=x-y
	print x,"-",y,"=",c
def mul(x,y):
	c=x*y
	print x,"*",y,"=",c
def div(x,y):
	c=x/y
	print x,"/",y,"=",c
def mod(x,y):
	c=x%y
	print x,"%",y,"=",c
if C==6:
	def f(n):
		if n==1:
			print n
			return n
		else:
			print n,"*",
			return n*f(n-1)
	n=input("enter your no here: ")
	print f(n)
if C==1:
	a=input("Enter your first no here: ")
	b=input("Enter your second no here: ")
	add(a,b)
elif C==2:
	a=input("Enter your first no here: ")
	b=input("Enter your second no here: ")
	sub(a,b)
elif C==3:
	a=input("Enter your first no here: ")
	b=input("Enter your second no here: ")
	mul(a,b)
elif C==4:
	a=input("Enter your first no here: ")
	b=input("Enter your second no here: ")	
	div(a,b)
elif C==5:
	a=input("Enter your first no here: ")
	b=input("Enter your second no here: ")
	mod(a,b)
def first(word):
	return word[0]
def last(word):return word[-1]
def middle(word):
	return word[1:-1]
def palindrome(word):
	if first(word)==last(word):
		word = middle(word)
		n=len(word)
		if n<2:
			print "palindrome"
		else:		
			return palindrome(word)
	else:
		print "not palindrome"


word=raw_input("Enter the  string:")
palindrome(word)

所有数字的总和

[编辑 | 编辑源代码]
def sum_of_n_numbers(number):
	if(number==0):
		return 0
	else:
		return number + sum_of_n_numbers(number-1)
num = raw_input("Enter a number:")
num=int(num)
sum = sum_of_n_numbers(num)
print sum
###another answer in case of while loops
def sum_of_Digits(number):
	sum=0
	while number>0:
		digit=number%10
		sum=sum+digit
		number=number/10
	return sum
num=raw_input("enter the number")
num=int(num)
sum_of_digits=sum_of_Digits(num)
print sum_of_digits

练习 18.5

[编辑 | 编辑源代码]
class Card(object):
	
	suit_names = ['Clubs', 'Diamonds', 'Hearts', 'Spades']
	rank_names = [None, 'Ace', '2', '3', '4', '5', '6', '7', 
					'8', '9', '10', 'Jack', 'Queen', 'King']
			
	def __init__(self, suit = 0, rank = 2):
		self.suit = suit
		self.rank = rank
	
	def __str__(self):
		return '%s of %s' % (Card.rank_names[self.rank], 
							Card.suit_names[self.suit])
							
	def __cmp__(self, other):
		c1 = (self.suit, self.rank)
		c2 = (other.suit, other.rank)
		return cmp(c1, c2)
		
	def is_valid(self):
		return self.rank > 0
		
class Deck(object):
	
	def __init__(self, label = 'Deck'):
		self.label = label
		self.cards = []
		for i in range(4):
			for k in range(1, 14):
				card = Card(i, k)
				self.cards.append(card)
				
	def __str__(self):
		res = []
		for card in self.cards:
			res.append(str(card))
		print self.label
		return '\n'.join(res)
		
		
	def deal_card(self):
		return self.cards.pop(0)
		
	def add_card(self, card):
		self.cards.append(card)
	
	def shuffle(self):
		import random
		random.shuffle(self.cards)
		
	def sort(self):
		self.cards.sort()
		
	def move_cards(self, other, num):
		for i in range(num):
			other.add_card(self.deal_card())
	
	def deal_hands(self, num_hands, num_cards):
		if num_hands*num_cards > 52:
			return 'Not enough cards.'
		
		l = []
		
		for i in range(1, num_hands + 1):
			hand_i = Hand('Hand %d' % i)
			self.move_cards(hand_i, num_cards)
			l.append(hand_i)
		
		return l

class Hand(Deck):
	
	def __init__(self, label = ''):
		self.cards = []
		self.label = label

# 18-6, 1-4:
class PokerHand(Hand):
	
	def suit_hist(self):
		self.suits = {}
		for card in self.cards:
			self.suits[card.suit] = self.suits.get(card.suit, 0) + 1
		return self.suits
		
	def rank_hist(self):
		self.ranks = {}
		for card in self.cards:
			self.ranks[card.rank] = self.ranks.get(card.rank, 0) + 1
		return self.ranks
	
	def P(self):
		self.rank_hist()
		for val in self.ranks.values():
			if val >= 2:
				return True
		return False
	
	def TP(self):
		self.rank_hist()
		count = 0
		for val in self.ranks.values():
			if val == 4:
				return True
			elif val >= 2 and val < 4:
				count += 1
		return count >= 2
		
	def TOAK(self):
		self.rank_hist()
		for val in self.ranks.values():
			if val >= 3:
				return True
		return False
	
	def STRseq(self):
		seq = []
		l = STRlist()
		self.rank_hist()
		h = self.ranks.keys()
		h.sort()
		if len(h) < 5:
			return []
		
		# Accounts for high Aces:
		if 1 in h:
			h.append(1)
		
		for i in range(5, len(h)+1):
			if h[i-5:i] in l:
				seq.append(h[i-5:i])
		return seq
	
	def STR(self):
		seq = self.STRseq()
		return seq != []

	def FL(self):
		self.suit_hist()
		for val in self.suits.values():
			if val >= 5:
				return True
		return False

	def FH(self):
		d = self.rank_hist()
		keys = d.keys()
		
		for key in keys:
			if d[key] >= 3:
				keys.remove(key)
				for key in keys:
					if d[key] >= 2:
						return True
		return False
		
	def FOAK(self):
		self.rank_hist()
		for val in self.ranks.values():
			if val >= 4:
				return True
		return False
		
	def SFL(self):
		seq = self.STRseq()
		if seq == []:
			return False
		for list in seq:
			list_suits = []
			for index in list:
				for card in self.cards:
					if card.rank == index:
						list_suits.append(card.suit)
			list_hist = histogram(list_suits)
			for key in list_hist.keys():
				if list_hist[key] >= 5:
					return True
		return False
				
	def classify(self):
		self.scores = []
		hands = ['Pair', 'Two-Pair',
		'Three of a Kind', 'Straight',
		'Flush', 'Full House',
		'Four of a Kind', 'Straight Flush']
		if self.P():
			self.scores.append(1)
		if self.TP():
			self.scores.append(2)
		if self.TOAK():
			self.scores.append(3)
		if self.STR():
			self.scores.append(4)
		if self.FL():
			self.scores.append(5)
		if self.FH():
			self.scores.append(6)
		if self.FOAK():
			self.scores.append(7)
		if self.SFL():
			self.scores.append(8)
		if self.scores != []:
			return hands[max(self.scores)-1]
	
def STRlist():
	s = []
	for i in range(0,9):
		s.append(range(1,14)[i:i+5])
	s.append([10,11,12,13,1])	
	return s

def histogram(l):
	d = dict()
	for k in range(len(l)):
		d[l[k]] = 1 + d.get(l[k],0)
	return d

# 18-6, 5:
def p(config = '', trials = 10000, n = 1):
	"""Estimates probability that the
	nth dealt hand will be config. A hand
	consists of seven cards."""
	
	successes = 0
	
	for i in range(1, trials + 1):
		deck = Deck('Deck %d' % i)
		deck.shuffle()
		
		box = Hand()
		deck.move_cards(box, (n-1)*7)
		
		hand = PokerHand('Poker Hand %d' % i)
		deck.move_cards(hand, 7)
		if hand.classify() == config:
			successes += 1
	
	return 1.0*successes/trials

#Iterate until first desired config.:
if __name__ == '__main__':
	
	c = 1
	
	while True:
		deck = Deck()
		deck.shuffle()
		hand = PokerHand('Poker Hand %d' % c)
		deck.move_cards(hand, 5)
		print hand
		print hand.SFL()
		if hand.SFL():
			print hand.STRseq()
			break
		print ''
		c += 1

Code by Victor Alvarez

练习 B.1

[编辑 | 编辑源代码]

阅读维基百科关于大 O 符号的页面并回答以下问题

1. n³ + n² 的增长阶数是多少?1000000n³ + n² 呢?n³ + 1000000n² 呢?

答:都是 O(n³)

2. (n² + n) · (n + 1) 的增长阶数是多少?在你开始相乘之前,请记住你只需要最高阶项。

答:O(n³)

3. 如果 f 属于 O(g),对于某个未指定的函数 g,我们可以对 af + b 说些什么,其中 a 和 b 是常数?

答:a 和 b 也属于 O(g),因为 O 符号使用最高阶系数。常数属于 O(1),所以在这种情况下它们无关紧要。

4. 如果 f1 和 f2 属于 O(g),我们可以对 f1 + f2 说些什么?

答:假设作者的意思是本题中的 g 与上一题中的 g 不同,那么 O(g) 保持不变。

5. 如果 f1 属于 O(g) 且 f2 属于 O(h),我们可以对 f1 + f2 说些什么?

答:f1 + f2 可能匹配也可能不匹配 O(g) 和 O(h) 中的较高增长阶数。如果 f1 或 f2 是最高阶系数,那么 f1 + f2 将具有与 O(g) 或 O(h) 中的较大增长阶数相同的增长阶数。如果不是这样,那么我们对 f1 + f2 的增长阶数一无所知。也就是说,它们相加与否并不重要。

6. 如果 f1 属于 O(g) 且 f2 属于 O(h),我们可以对 f1 · f2 说些什么?

答:这不同。如果 f1 和 f2 相乘(并且假设它们都包含 n),那么 O(f1 · f2) 必须是 O(n) 或更大。如果 f1 是 n³,例如,它可能会更大,但它必须至少是 O(n)。


练习 B.3

[编辑 | 编辑源代码]

编写一个名为 bisection 的函数,它接受一个排序列表和一个目标值,并在列表中返回该值的索引(如果存在),或者如果不存在则返回 None

from bisect import bisect_left

def bisection(sorted_list, item):
    i = bisect_left(sorted_list, item)
    if i < len(sorted_list) and sorted_list[i] == item:
        return i
    else:
        return None

if __name__ == '__main__':
    a = [1, 2, 3]
    print(bisection(a, 2))  # expect 1
    b = [1, 3]
    print(bisection(b, 2))  # expect None
    c = [1, 2]
    print(bisection(c, 3))  # expect None
华夏公益教科书