6–1. 字符串.
string 模塊中是否有一種字符串方法或者函數可以幫我鑑定一下一個字符串是否是另一個大字符串的一部分?
# coding=utf-8
__author__ = 'Ibuki Suika'
if __name__ == '__main__':
s1 = raw_input('input a string: ')
s2 = raw_input('input a substring: ')
print(s1.find(s2) <> -1)
6–2. 字符串標識符.
修改例6-1 的idcheck.py 腳本,使之可以檢測長度爲一的標識符,並且可以識別Python 關鍵字,對後一個要求,你可以使用keyword 模塊(特別是keyword.kelist)來幫你.
import string
import keyword
alphas = string.letters + '_'
nums = string.digits
keywords = keyword.kwlist
print 'Welcome to the Identifier Checker v2.0'
myInput = raw_input('Identifier to test? ')
if myInput[0] not in alphas:
print 'invalid: first symbol must be alphabetic'
else:
sets = alphas + nums
mark = True
for ch in myInput[1:]:
if ch not in sets:
print 'invalid: remaining symbols must be alphanumeric'
mark = False
break
if myInput in keywords:
print "invalid: can't be keywords"
mark = False
if mark:
print 'okay as an identifier'
6–3. 排序
(a) 輸入一串數字,從大到小排列之.
(b) 跟a 一樣,不過要用字典序從大到小排列之.
# coding=utf-8
__author__ = 'Ibuki Suika'
if __name__ == '__main__':
s = raw_input('input some numbers: ').split()
nums = [int(i) for i in s]
nums.sort()
nums.reverse()
print(nums)
s.sort()
s.reverse()
print(s)
6–4. 算術.
更新上一章裏面你的得分測試練習方案,把測試得分放到一個列表中去.你的代碼應該可以計算出一個平均分,見練習2-9 和練習5-3.
def level(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
elif score >= 60:
return 'D'
else:
return 'F'
str = raw_input('your scores: ').split()
average = 0
scores = []
for n in str:
num = int(n)
scores.append(level(num))
average += num
average /= float(len(scores))
print 'average score is %.2f' % average
print scores
6–5. 字符串
(a)更新你在練習2-7 裏面的方案,使之可以每次向前向後都顯示一個字符串的一個字符.
(b)通過掃描來判斷兩個字符串是否匹配(不能使用比較操作符或者cmp()內建函數)。附加題:在你的方案里加入大小寫區分.
(c)判斷一個字符串是否重現(後面跟前面的一致).附加題:在處理除了嚴格的迴文之外,加入對例如控制符號和空格的支持。
(d)接受一個字符,在其後面加一個反向的拷貝,構成一個迴文字符串.
s = raw_input('string: ')
for ch in s:
print ch,
print
for ch in reversed(s):
print ch,
def issame(str1, str2, sens = False):
if len(str1) != len(str2):
return False
for i, ch in enumerate(str1):
if not sens:
if ch.upper() != str2[i].upper():
break
else:
if ch != str2[i]:
break
else:
return True
return False
str1 = raw_input('str1: ')
str2 = raw_input('str2: ')
print issame(str1, str2)
print issame(str1, str2, True)
def isreverse(s):
size = len(s)
for i in range(size // 2):
if s[i] != s[size - i - 1]:
return False
return True
s = raw_input('str: ')
print isreverse(s)
def add_reverse(s):
return s + s[::-1]
s = raw_input('s: ')
print add_reverse(s)
6–6. 字符串.
創建一個string.strip()的替代函數:接受一個字符串,去掉它前面和後面的空格(如果使用string.*strip()函數那本練習就沒有意義了)
def trim(s):
start = 0
for i in xrange(len(s)):
if not s[i].isspace():
start = i
break
end = -1
for i in xrange(-1, -len(s), -1):
if not s[i].isspace():
end = i
break
end = None if end == -1 else end + 1
return s[start:end]
s = trim(raw_input('str: '))
print s
print 'len = %d' % len(s)
6–7. 調試.看一下在例6.5 中給出的代碼(buggy.py)
(a)研究這段代碼並描述這段代碼想做什麼.在所有的(#)處都要填寫你的註釋.
(b)這個程序有一個很大的問題,比如輸入6,12,20,30,等它會死掉,實際上它不能處理任何的偶數,找出原因.
(c)修正(b)中提出的問題.
Example 6.4 有bug 的程序(buggy.py)
這是一個用於練習6-7 的程序,判斷這個程序是幹什麼的,在"#"處添加你的註釋,找出其中的錯
誤,並修改之.
1 #!/usr/bin/env python
2
3 #
4 num_str = raw_input('Enter a number: ')
5
6 #
7 num_num = int(num_str)
8
9#
10 fac_list = range(1, num_num+1)
11 print "BEFORE:", 'fac_list'
Edit By Vheavens
Edit By Vheavens
12
13 #
14 i = 0
15
16 #
17 while i < len(fac_list):
18
19 #
20 if num_num % fac_list[i] == 0:
21 del fac_list[i]
22
23 #
24 i = i + 1
25
26 #
27 print "AFTER:", 'fac_list'
#!/usr/bin/env python
#提示輸入一個字符串
num_str = raw_input('Enter a number: ')
#把輸入的字符串轉換爲整數
num_num = int(num_str)
#產生1到num_num的數字列表,並輸出
fac_list = range(1, num_num+1)
print "BEFORE:", fac_list
#初始化下標爲0
i = 0
#遍歷列表
while i < len(fac_list):
#清除num_num的因數
if num_num % fac_list[i] == 0:
del fac_list[i]
#下標加1
i = i + 1
#輸出去除num_num的所有因數後的列表
print "AFTER:", fac_list
#這段程序的問題在於,del一個列表元素後,列表的長度也會發生改變,在刪除一個元素的時候,下標也會受到影響,會導致有的元素被遺漏。修改如下:
#!/usr/bin/env python
#提示輸入一個字符串
num_str = raw_input('Enter a number: ')
#把輸入的字符串轉換爲整數
num_num = int(num_str)
#產生1到num_num的數字列表,並輸出
fac_list = range(1, num_num+1)
print "BEFORE:", fac_list
#初始化下標爲0
i = 0
#遍歷列表
while i < len(fac_list):
#清除num_num的因數
if num_num % fac_list[i] == 0:
del fac_list[i]
i = i - 1
#下標加1
i = i + 1
#輸出去除num_num的所有因數後的列表
print "AFTER:", fac_list
6–8. 列表.
給出一個整數值,返回代表該值的英文,比如輸入89 返回"eight-nine"。
附加題:能夠返回符合英文語法規則的形式,比如輸入“89”返回“eighty-nine”。本練習中的值限定在家0到1,000.
def translate(num):
assert 0 <= num < 1000, 'out of bound'
num_str1 = ['zero', 'one', 'two', 'three', 'four', 'five', 'six',
'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve',
'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen',
'eighteen', 'nineteen']
num_str2 = ['twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy',
'eighty', 'ninety']
num_str3 = ' hundred '
s = '' if num != 0 else num_str1[0]
n = num // 100
if n > 0:
s = num_str1[n] + num_str3
n = num % 100
if 0 < n < 20:
s = s + num_str1[n]
elif n >= 20:
s = s + num_str2[num // 10 % 10 - 2] + ('-' + num_str1[num % 10] if num % 10 != 0 else '')
return s
print [translate(num) for num in range(1000)]
6–9. 轉換.
爲練習5-13 寫一個姊妹函數, 接受分鐘數, 返回小時數和分鐘數. 總時間不變,並且要求小時數儘可能大.
def trans_time(mins):
hours = mins // 60
minutes = mins % 60
return (hours, minutes)
mins = input('minutes: ')
print '%d:%d' % trans_time(mins)
6–10.字符串.
寫一個函數,返回一個跟輸入字符串相似的字符串,要求字符串的大小寫反轉.比如,輸入"Mr.Ed",應該返回"mR.eD"作爲輸出.
def reverse_case(s):
result = ''
for ch in s:
if ch.islower():
result += ch.upper()
elif ch.isupper():
result += ch.lower()
else:
result += ch
return result
s = raw_input('string: ')
print reverse_case(s)
6–11.轉換
(a)創建一個從整數到IP 地址的轉換程序,如下格式: WWW.XXX.YYY.ZZZ.
(b)更新你的程序,使之可以逆轉換.
def int2ip(num):
ip = [(num >> i & 0xff) for i in xrange(24, -1, -8)]
return '%d.%d.%d.%d' % tuple(ip)
def ip2int(ip):
temp = ip.split('.')
temp = [int(part) for part in temp]
temp = [temp[3-i//8] << i for i in xrange(24, -1, -8)]
return sum(temp)
num = input('number: ')
s = int2ip(num)
print s
print ip2int(s)
6–12.字符串
(a)創建一個名字爲findchr()的函數,函數聲明如下:
def findchr(string, char)
findchr()要在字符串string 中查找字符char,找到就返回該值的索引,否則返回-1.不能用string.*find()或者string.*index()函數和方法
(b)創建另一個叫rfindchr()的函數,查找字符char 最後一次出現的位置.它跟findchr()工作類似,不過它是從字符串的最後開始向前查找的.
(c)創建第三個函數,名字叫subchr(),聲明如下:
def subchr(string, origchar, newchar)
subchr()跟findchr()類似,不同的是,如果找到匹配的字符就用新的字符替換原先字符.返回修改後的字符串.
def findchr(string, char):
index = -1
for i, ch in enumerate(string):
if (ch == char):
index = i
break
return index
def rfindchr(string, char):
index = -1
for i, ch in enumerate(string[::-1]):
if ch == char:
index = len(string) - i - 1
break
return index
def subchr(string, oldchar, newchar):
s = ''
for ch in string:
if ch == oldchar:
s += newchar
else:
s += ch
return s
6–13.字符串.
string 模塊包含三個函數,atoi(),atol(),和atof(),它們分別負責把字符串轉換成整數,長整型,和浮點型數字.從Python1.5 起,Python 的內建函數int(),long(),float()也可以做相同的事了,complex()函數可以把字符串轉換成複數.(然而1,5 之前,這些轉換函數只能工作於數字之上)
string 模塊中並沒有實現一個atoc()函數,那麼你來實現一個,atoc(),接受單個字符串做參數輸入,一個表示複數的字符串,例如,'-1.23e+4-5.67j',返回相應的複數對象.你不能用eval()函數,但可以使用complex()函數,而且你只能在如下的限制之下使用complex():complex(real,imag)的real 和imag 都必須是浮點值.
def atoc(string):
index = max(string.rfind('+'), string.rfind('-'))
if index > 0:
if string[index-1] == 'e':
index = max(string.rfind('+', 0, index-1), string.rfind('-', 0, index-1))
real = float(string[0:index])
imag = float(string[index:len(string)-1])
else:
if 'j' in string:
real = 0
imag = float(string[0:len(string)-1])
else:
real = float(string)
imag = 0
return complex(real, imag)
6–14.隨機數.設計一個"石頭,剪子,布"遊戲,有時又叫"Rochambeau",你小時候可能玩過,下面是規則.你和你的對手,在同一時間做出特定的手勢,必須是下面一種手勢:石頭,剪子,布.勝利者從下面的規則中產生,這個規則本身是個悖論.
(a) the paper covers the rock,布包石頭.
(b)石頭砸剪子,
(c)剪子剪破布.
在你的計算機版本中,用戶輸入她/他的選項,計算機找一個隨機選項,然後由你的程序來決定一個勝利者或者平手.注意:最好的算法是儘量少的使用if 語句.
from random import randint
#石頭=0,剪子=1,布=2
def rochambeau(human):
robot = randint(0, 2)
win = (1, 2, 0)
return win[human] == robot
6–15.轉換
(a)給出兩個可識別格式的日期,比如 MM/DD/YY 或者 DD/MM/YY 格式,計算出兩個日期間的天數.
(b)給出一個人的生日,計算從此人出生到現在的天數,包括所有的閏月.
(c)還是上面的例子,計算出到此人下次過生日還有多少天.
import time
import datetime
def between(begin, end):
(year, month, day) = map(int, begin.split('-'))
d1 = datetime.datetime(year, month, day)
(year, month, day) = map(int, end.split('-'))
d2 = datetime.datetime(year, month, day)
return (d2- d1).days
print between('2011-3-22', '2011-7-26')
6–16.矩陣.
處理矩陣M 和N 的加和乘操作.
from operator import add, mul
def matrix_add(m1, m2):
m3 = []
for i, item in enumerate(m1):
m3 += [map(add, item, m2[i])]
return m3
def matrix_mul(m1, m2):
t = [[m2[i][j] for i in xrange(len(m2))] for j in xrange(len(m2[0]))]
m3 = [[sum(map(mul, item1, item2)) for item2 in t] for item1 in m1]
return m3
m1 = [[1, 2, 3], [3, 4, 1], [1, 2, 3]]
m2 = [[3, 2, 1], [2, 2, 2], [5, 1, 3]]
print matrix_add(m1, m2)
print matrix_mul(m1, m2)
6–17.方法.
實現一個叫myPop()的函數,功能類似於列表的pop()方法,用一個列表作爲輸入,移除列表的最新一個元素,並返回它.
def myPop(alist):
assert isinstance(alist, list)
alist.pop()
return alist
6–19.多列輸出.
有任意項的序列或者其他容器,把它們等距離分列顯示.由調用者提供數據和輸出格式.例如,如果你傳入100 個項並定義3 列輸出,按照需要的模式顯示這些數據.這種情況下,應
該是兩列顯示33 個項,最後一列顯示34 個.你可以讓用戶來選擇水平排序或者垂直排序.
#data:數據項,cols:列數,sort=0(不排序)、1(水平排序)、2(垂直排序)
def print_format(data, cols, sort = 0):
assert cols > 0
ls = [data[i:i+cols] for i in range(0, len(data), cols)]
if sort == 1:
for x in ls:
x.sort()
elif sort == 2:
#補足數據項
if len(ls[-1]) < cols:
for i in range(cols-len(ls[-1])):
ls[-1].append("")
temp = zip(*ls)
temp = [sorted(x) for x in temp]
ls = zip(*temp)
for x in ls:
for i in x:
print i, '\t',
print
data = [1, 3, 4, 7, 9, 10, 12, 4, 0, 12, 22]
print '多列輸出:'
print_format(data, 3)
print '水平排序:'
print_format(data, 3, 1)
print '垂直排序:'
print_format(data, 3, 2)