Python核心编程 第六章练习

笔者刚刚开始python的系统学习,所以在代码上还无法达到pythonic的水准,很多写法也都是按照C++的习惯来写的,希望能有前辈进行交流指导。

欢迎拍砖


6_2

#!/usr/bin/env python
# encoding: utf-8

import string
import keyword

alphas = string.letters + '_'
nums = string.digits
keywd = keyword.kwlist

print "Welcome to the Identifier Checker v2.0"
print "Testees must be 2 chars long"
isValid = False

myInput = raw_input('')

if len(myInput) > 1:
    if myInput[0] not in alphas:
        print """invalid: first symbol ust be alphabetic"""
    else:
        for otherChar in myInput[1:]:
            if otherChar not in alphas + nums:
                print """invalid: remaining symbols must be
                alphanumeric"""
                break
        else:
            isValid = True
        if myInput not in keywd and isValid:
            print """invalid: the input is a keyword itself"""
        else:
            print "okay as an identifier"

6_3

这道题目的中文版书籍翻译有误,原题是:b.Do the same thing, but for strings and in reverse alphabetical (largest-to-smallest lexicographic) order.中文版翻译为:(b) 跟 a 一样,不过要用字典序从大到小排列之.
这显然是不对的,因此笔者在此处翻译为:“跟a一样,不过要求输入的字符改变为英文字母串,按照从打到小排列(这个lexicographic的原意为词典,此处笔者理解为由英文字母组成的单词)

#!/usr/bin/env python
# encoding: utf-8

import string

def num_input():
    num = string.digits + '.'
    while True:
        isDigit = True
        try:
            lst_dgit = raw_input("Please input digit: ").split()
            for i in lst_dgit:
                for j in i:
                    if j not in num:
                        print i
                        isDigit = False
                        break
                if not isDigit:
                    break
            if isDigit:
                break
            else:
                print "You input is not all digits, Please do it again!"
        except (EOFError, KeyboardInterrupt, IndexError):
            break
    lst_num = [float(i) for i in lst_dgit]
    lst_num.sort(reverse = True)
    print lst_num

def string_input():
    alpha = string.uppercase + string.lowercase
    while True:
        isAlpha = True
        try:
            lst_alpha = raw_input("Please input string: ").split()
            for i in lst_alpha:
                for j in i:
                    if j not in alpha:
                        isAlpha = False
                        break
                if not isAlpha:
                    break
            if isAlpha:
                break
            else:
                print "Your input is not all lexicographic."
        except(EOFError, KeyboardInterrupt, IndexError):
            break
    lst_string = [str(i) for i in lst_alpha]
    lst_string.sort()
    print lst_string

CMDs = {'e': num_input, 's': string_input}

def showmenu():
    pr = '''
(S)tring
(D)igit
(Q)uit

Please select: '''
    while True:
        while True:
            try:
                choice = raw_input(pr).split()[0].lower()
            except(EOFError, KeyboardInterrupt, IndexError):
                choice = 'q'
            print '\nYou picked: [%s]' %choice
            if choice not in 'sdq':
                print 'Invalid option, try again'
            else: break
        if choice == 'q':
            break
        CMDs[choice]()

if __name__ == "__main__":
    showmenu() 

6_4

此题中,为了使得python能够使用常规的计算方式,而非采用“地板除”,引用了division模块。

#!/usr/bin/env python
# encoding: utf-8

from __future__ import division #to make the python do the real division

def Classify(value):
    if value > 90:
        return 'A'
    if value > 80:
        return 'B'
    if value > 70:
        return 'C'
    if value > 60:
        return 'D'
    else:
        return 'F'

if __name__ == "__main__":
    lst = [90, 93, 64, 34, 69]
    lst.sort()
    sum_lst = sum(lst)
    avg_lst = sum_lst/len(lst)
    print "the average grade is %0.2f" %avg_lst
    class_lst = [Classify(i) for i in lst]
    print class_lst

6_5

这个部分中文版的练习题翻译比较奇怪,跟正文的水准有些差距。对照了英文原文,将个人翻译写于此处。c小题的原文为:
c.Determine if a string is palindromic (the same backward as it is forward). Extra
credit: Add code to suppress symbols and whitespace if you want to process
anything other than strict palindromes.
翻译为:判断某个字符串是否是回文序列(正序与倒序保持一致)。附加题:添加代码,使得能够抑制符号以及空格,来判断非严格的回文序列。

6_5_a

#!/usr/bin/env python
# encoding: utf-8

if __name__ == "__main__":
    strInput = raw_input("Please input a string: ")
    print "The forward string is: "
    for i in strInput:
        print i,
    print '\n',
    print "The backward string is: "
    for i in strInput[::-1]:
        print i,
    print '\n'

6_5_b

#!/usr/bin/env python
# encoding: utf-8

if __name__ == "__main__":
    str1 = raw_input("Please input the 1st string: ").strip()
    str2 = raw_input("Please input the 2nd string: ").strip()
    #compare the length of the 2 strings
    isEqual = True
    if len(str1) == len(str2):
        for (i, j) in zip(str1, str2):
            if i != j:
                isEqual = False
                break
    if isEqual:
        print "the input is the same string!"
    else:
        print "Not the same string!"

6_5_c

#!/usr/bin/env python
# encoding: utf-8

import string
#availElem is all the character that can be used
availElem = string.digits + string.lowercase + string.uppercase


def palindrome(strToTest):
    str_lst = [i for i in strToTest if i in availElem]
    print str_lst
    if cmp(str_lst, str_lst[::-1]) == 0:
        print "It's palindrome!"
    else:
        print "It's not palindrome"

if __name__ == "__main__":
    strToTest = raw_input("Please input a string: ")
    palindrome(strToTest)

6_5_d

#!/usr/bin/env python
# encoding: utf-8

def palindrome(strToTest):
    strToTest += strToTest[::-1]
    print strToTest

if __name__ == "__main__":
    strToTest = raw_input("Please input a string: ")
    palindrome(strToTest)

6_6

#!/usr/bin/env python
# encoding: utf-8

if __name__ == "__main__":
    strToStrip = raw_input("Please input the string: ")
    for iStart in range(len(strToStrip)):
        if strToStrip[iStart] != ' ':
            break
    for iEnd in range(len(strToStrip)):
        if strToStrip[-iEnd-1] != ' ':
            break
    strResult = strToStrip[iStart: -iEnd]
    print strResult

6_10

#!/usr/bin/env python
# encoding: utf-8

import string

lowstring = string.lowercase
uppstring = string.uppercase

strTmp = raw_input("Please input a string: ")
strRe = str()
for i in strTmp:
    if i in lowstring:
        strRe += i.upper()
    elif i in uppstring:
        strRe += i.lower()
    else:
        strRe += i
print strRe

6_11

这个题目不大会,搜索到了一个答案,出自林中路的答案,在他的基础上做了点小修改。 链接是:http://juven.blog.51cto.com/749867/975560,看了一下人家写的答案,差距一下就出来了。还是前辈厉害!
同时,这里使用了sys.argv[1], 应该是和C++的表示意义是一样的。

#!/usr/bin/env python
# encoding: utf-8

def intToIp(num):
    dotIPAdd = str()
    for i in range(3, -1, -1):
        dotIPAdd += str(num / (256 ** i)) + '.'
        if i == 3 and int(dotIPAdd.strip('.')) > 255:
            print "Invalid IP, please enter another number ..."
            sys.exit(1)
        num = num % (256 ** i)
    return (dotIPAdd.rstrip('.'))

if __name__ == "__main__":
    import sys
    num = int(sys.argv[1])
    print intToIp(num)

6_11

这里要注意for…else的用法,else在这里还暗含程序不是通过break实现的意思,因此可以用来检测程序是否顺利执行完毕。

#!/usr/bin/env python
# encoding: utf-8

def intToIp(num):
    dotIPAdd = str()
    for i in range(3, -1, -1):
        dotIPAdd += str(num / (256 ** i)) + '.'
        if i == 3 and int(dotIPAdd.strip('.')) > 255:
            print "Invalid IP, please enter another number ..."
            sys.exit(1)
        num = num % (256 ** i)
    return (dotIPAdd.rstrip('.'))

if __name__ == "__main__":
    import sys
    num = int(sys.argv[1])
    print intToIp(num)

6_13

此题的解答是有问题的,我定义的这种方式是在字符串的末尾反向寻找+-号,然后将两边分为实数和复数部分,但这种查找方式如果输入的值为3+3e+4j时,就会出现问题。暂且把不成熟的答案写在这里,希望有前辈能提供修改意见。

#!/usr/bin/env python
# encoding: utf-8

import string

def atoc(str2c):
    pos_plus = 0
    pos_minus = 0
    if '+' in str2c:
        pos_plus = str2c.rfind('+')
    if '-' in str2c:
        pos_minus = str2c.rfind('-')
    pos = max(pos_plus, pos_minus)
    num_real = float(str2c[0:pos])
    num_imag = float(str2c[pos+1: len(str2c)-1])
    return complex(num_real, num_imag)

if __name__ == "__main__":
    import sys
    compS = atoc(sys.argv[1])
    print compS

6_14

这道问题解的不是很巧,具体的竞技过程是电脑随机选取一个用数字表示的选择:Paper for 0, Rock for 1, Scissor for 2。用户通过输入英文字符选择自己要出的手势,然后通过字典查询到其对应手势的数值,将电脑和人的数值相减就可以得到比赛的结果。但这种方法if使用仍然较多,不知道如何才能简化。

#!/usr/bin/env python
# encoding: utf-8

def Rochambeau():
    pr = '''(P)aper
    (R)ock
    (S)cissor
    (Q)uit

    Please choose one
    '''
    import random
    #the computer choose a random choice
    trick_com = random.randrange(0, 3)
    dct_choice = {'p': 0, 'r': 1, 's': 2}
    while True:
        try:
            choice = raw_input(pr).split()[0].lower()
            except (EOFError, KeyboardInterrupt, IndexError):
            choice = 'q'
        print '\nYou picked: [%s]' %choice
        if choice not in 'prsq':
            print "please choose the right choice!"
            continue
        break
    if choice == 'q':
        return
    result =  dct_choice[choice] - trick_com
    if result == -1 or result == 2:
        print "you win!"
    elif result == 0:
        print "It's a tie"
    else:
        print "You lose!"
if __name__ == "__main__":
    Rochambeau()

6_15

这道题目中,同样参考了林中路前辈的答案。链接再次挂出http://juven.blog.51cto.com/749867/975560
这个题目中,注意datetime模块的使用,在该模块中我试图使用datetime.date(),直接通过参数传递一个元组类型的变量,被提示只能分开传递,很是郁闷。
另外,这注意now变量,我的原意是希望通过datetime.datetime.now()直接赋值给D3,然后将D3直接与其他变量进行加减,结果报错。后来只好用了这个傻办法,将datetime的信息截取为date了。必须承认这道题目我的解法一点都不优雅。羞愧捂脸

#!/usr/bin/env python
# encoding: utf-8

def convert2Date(strDate):
    lstDate = strDate.split('/')
    tupDate = (int(lstDate[-1]), int(lstDate[0]), int(lstDate[1]))
    return tupDate

if __name__ == "__main__":
    import datetime
    strDate1 = raw_input("Enter the date: ")
    strDate2 = raw_input("Enter another date: ")
    tupDate1 = convert2Date(strDate1)
    tupDate2 = convert2Date(strDate2)
    D1 = datetime.date(tupDate1[0], tupDate1[1], tupDate1[2])
    D2 = datetime.date(tupDate2[0], tupDate2[1], tupDate2[2])
    print (D2-D1).days
    now = datetime.datetime.now()
    D3 = datetime.date(now.year, now.month, now.day)
    #b
    print (D3-D1).days
    #c
    D4 = datetime.date(D3.year, D1.month, D1.day)
    deltaDays = (D4-D3).days
    if deltaDays > 0:
        print deltaDays
    else:
        print (datetime.date(D3.year+1, D1.month, D1.day)
               - D3).days

6_16

这道题目的安排有点奇怪,不知道原意是否是让我们自己写一个函数,我偷了懒,查阅网络之后,发现其实第5章中提到了numpy的module很适合在此处使用,暂且把numpy当做我使用的第一个轮子吧!

#!/usr/bin/env python
# encoding: utf-8

import numpy as np
M = np.array([[2, 3], [1, 5]])
N = np.array([[1, 4], [4, 6]])
print M + N
print np.dot(M, N)

6_17

#!/usr/bin/env python
# encoding: utf-8

def myPop(lst):
    sizeoflst = len(lst)
    lstElement = lst[sizeoflst-1]
    del lst[sizeoflst-1]
    return lstElement

if __name__ == "__main__":
    lst = [3, 6, 7, 0 ,3]
    print lst
    print myPop(lst)
    print lst
    print myPop(lst)
    print lst

6_19

这一部分真是写的又臭又长,为了使用一下迭代的思想,把自己给坑进去了。注意阅读代码的话,会发现有两个参数numOfRow, leftRow刚刚开始的时候是同一个值。这里我是希望用leftRow来表示还剩下的行数,然后用numOfRow用来做序号的步长。安排的不大合理,但是我暂时想不出合适的办法。
另外,这道题目我把用户输入的数组的环节给略去了,因为实在要输起来意义不大,用个raw_input().split()就可以获取到了。所以这里直接默认了一个0-99的数组,方便测试使用。

#!/usr/bin/env python
# encoding: utf-8

def Arrange(strHV, numOfRow, leftRow, lst, iStart):
    if leftRow == 0:
        return
    numOfLine = (len(lst)-iStart)/numOfRow
    leftRow -= 1
    if strHV == "h":
        for i in range(iStart, iStart + numOfLine):
            print lst[i],
        iStart += numOfLine
    else:
        for i in range(iStart, 100, numOfRow):
            print lst[i],
        iStart += 1
    print ''
    Arrange(strHV, numOfRow,leftRow, lst, iStart)

def main():
    pr = '''(H)orizontal
(V)ertical
(Q)uit

Choice one please: '''
    while True:
        try:
            choice = raw_input(pr).split()[0].lower()
        except(EOFError, KeyboardInterrupt, IndexError):
            choice = 'q'
        print '\nYou picked: [%s]' %choice
        if choice not in 'hvq':
            print "Please choose the right choice!"
            continue
        break
    if choice == 'q':
        return
    numOfRow = int(raw_input("Please input the number of the row: "))
    lst = range(100)
    Arrange(choice, numOfRow,numOfRow, lst, 0)

if __name__ == "__main__":
    main()

后记

这段时间一方面在忙着找实习,白天要做老师的课题项目,晚上见缝插针的,终于把这章的习题完成了,接下来我将继续完成下面几章的内容。
之所以开通这个博客倒不是希望阅读量多大,只是作为一个自己记录学习的地方,算是作为一个非科班的程序员的成长之路吧。
最后,真诚的希望未来能向各位前辈多多讨教。以上!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值