《Python核心编程》第13章 习题

来源:互联网 发布:15年网络流行关键词 编辑:程序博客网 时间:2024/06/05 15:59

13-3.对类进行定制。写一个类,用来将浮点型值转换为金额。

class MoneyFmt(object):    def __init__(self,value=0.0,flag='-'):        self.mvalue = float(value)        self.flag = flag            def dollarize(self):        val = round(self.mvalue,2)        strvalue = str(val)        pos = strvalue.find('.')        while (pos-3)>0:            strvalue = strvalue[:pos-3]+','+strvalue[pos-3:]            pos -= 3        if strvalue.startswith('-'):            return self.flag+'$'+strvalue[1:]        else:            return '$'+strvalue            def update(self,newvalue=None):        if newvalue is not None:            self.mvalue = float(newvalue)                def __nonzero__(self):        if (self.mvalue == 0):            return False        else:            return True            def __str__(self):        return self.dollarize()    def __repr__(self):        return repr(self.mvalue)
13-4.用户注册。

建立一个用户数据库类,来管理一个系统,该系统要求用户在登录后才能访问某些资源。这个数据库类对用户进行管理,并在实例化操作时加载之前保存的用户信息,提供访问函数来添加或更新数据库的信息。在数据修改后,数据库会在垃圾回收时将新信息保存到磁盘。

from datetime import datetimeimport shelve,osclass userdatabase(object):    def __init__(self,dbfile):        self.db = {}        if os.path.exists(dbfile):            self.db = shelve.open(dbfile, 'c')        self.dbfile = dbfile        self.flag = False    def __del__(self):        data = shelve.open(self.dbfile, 'c')          data.update(self.db)          data.close()    def login(self,user,pwd):        if not self.db.has_key(user):            self.flag = False        elif self.db[user][0] == pwd:            self.db[user][1] = datetime.now()            self.flag = True    def deluser(self,user):        if self.flag:            self.db.pop(user)        else:            print 'login first'    def updateuser(self,user,pwd):        if self.flag:            self.db[user] = [pwd,datetime.now()]        else:            print 'login first'    def listall(self):        if self.flag:            for user in self.db:                print user, self.db[user][0], self.db[user][1]        else:            print 'login first'if __name__=='__main__':    user = userdatabase("shelve.data")    user.login('root','root')    user.updateuser('test1','test1')    user.updateuser('test2','test2')    user.listall()
13-5.几何。创建一个由有序数值对(x,y)组成的Point类,代表某个点的X和Y坐标。
class point(object):    def __init__(self,x=0,y=0):        self.x = x        self.y = y    def __str__(self):        return '(%d,%d)' %(self.x,self.y)if __name__=='__main__':    p = point(3,4)    print p
13-6.几何。创建一个直线类,除主要属性:一对坐标值外,它还具有长度和斜线属性。你需要覆盖__repr__()方法,使得代表那条直线的字符串表示形式是由一对元组构成的元组。
from math import sqrtclass Line(object):    def __init__(self,x1=0,y1=0,x2=1,y2=0):        self.x1 = x1        self.y1 = y1        self.x2 = x2        self.y2 = y2        self.length = 0        self.slope = 0    def getLength(self):        if (self.x1 == self.x2) and (self.y1 == self.y2):            self.length = 0        elif (self.x1 == self.x2):            self.length = abs(self.y2-self.y1)        elif (self.y1 == self.y2):            self.length = abs(self.x2-self.x1)        else:            self.length = sqrt((self.y2 - self.y1)**2 + (self.x2 - self.x1)**2)        return self.length    def getSlope(self):        if self.length == 0:            self.slope = None        elif (self.x1 == self.x2) or (self.y1 == self.y2):            self.slope = None        else:              self.slope = float(self.y2 - self.y1) / (self.x2 - self.x1)          return self.slope    def __str__(self):        return '((%d,%d),(%d,%d))' %(self.x1,self.y1,self.x2,self.y2)    __repr__ = __str__if __name__=='__main__':    l = Line(1,2,1,4)    print l    print 'length is %f ' %l.getLength()    print 'slope is %s ' %l.getSlope()
13-7.数据类。提供一个time模块的接口,允许用户按照自己给定的时间格式来查看日期。你的类应该维护一个日期值,并用给定的时间创建一个实例,如果没有给出时间值,程序执行时会默认采用当前的系统时间。 

import timeclass TimeFormat(object):    def __init__(self,t=time.time()):        self.mytime = t    def update(self,t=time.time()):        self.mytime = t    def display(self,ft=None):        fmt = {}        fmt['MDY'] = '%m/%d/%y'        fmt['MDYY'] = '%m/%d/%Y'        fmt['DMY'] = '%d/%m/%y'        fmt['DMYY'] = '%d/%m/%Y'        fmt['MODYY'] = '%b %d,%Y'        if ft in fmt:            mt = time.localtime(self.mytime)            print time.strftime(fmt[ft],mt)        else:            print time.ctime(self.mytime)if __name__=='__main__':    tf = TimeFormat()    tf.display()    tf.display('MDY')    tf.display('MDYY')    tf.display('DMY')    tf.display('DMYY')    tf.display('MODYY')    tf.update(time.time()+5)    tf.display()
13-8.堆栈类。

实现一个堆栈类,类中应该有push()和pop()方法,还有一个isempty()方法,如果堆栈是空的,返回布尔值1,否则返回0。

class Stack(object):    def __init__(self,s=[]):        self.s = s    def isempty(self):        if len(self.s) == 0:            return 1        else:            return 0    def push(self,elm):        print 'pushed [',elm,']'        self.s.append(elm)    def peek(self):        if self.isempty():            print 'can not peek from an empty stack'        else:            return self.s[-1]                        def pop(self):        if self.isempty():            print 'can not pop from an empty stack'        elif 'pop' in dir(self.s):            print 'removed [',self.s.pop(),']'        else:            print 'removed [',self.peek(),']'            self.s.remove(self.peek())    def viewstack(self):        print self.sif __name__=='__main__':    s = Stack([1,2])    s.viewstack()    s.pop()    s.viewstack()    s.push(2)    s.viewstack()
13-9.队列类。实现一个队列类,这个类必须支持下面几种方法:enqueue()在队列的尾部加入一个新的元素,dequeue()在队列的头部取出一个元素,返回它并且把它从列表中删除。
class Queue(object):    def __init__(self,q=[]):        self.q = q    def isempty(self):        if len(self.q) == 0:            return 1        else:            return 0    def enqueue(self,elm):        print 'enter queue [',elm,']'        self.q.append(elm)                       def dequeue(self):        if self.isempty():            print 'can not dequeue from an empty queue'        else:            print 'removed [',self.q[0],']'            self.q.remove(self.q[0])    def viewqueue(self):        print self.qif __name__=='__main__':    q = Queue([1,2])    q.viewqueue()    q.dequeue()    q.viewqueue()    q.enqueue(1)    q.viewqueue()
13-10.堆栈和队列。编写一个类,定义一个能够同时具有堆栈和队列操作行为的数据结构。这个类和Perl语言中数组相像。需要实现四个方法。

class PerlArray(object):    def __init__(self,pa=[]):        self.pa = pa    def isempty(self):        if len(self.pa) == 0:            return 1        else:            return 0    def shift(self):        if self.isempty():            print 'can not pop from an empty perlarray'        else:            print 'shifted [',self.pa[0],']'            self.pa.remove(self.pa[0])    def unshift(self,elm):        print 'unshifted [',elm,']'        self.pa.insert(0,elm)    def push(self,elm):        print 'pushed [',elm,']'        self.pa.append(elm)                       def pop(self):        if self.isempty():            print 'can not pop from an empty perlarray'        else:            print 'removed [',self.pa[-1],']'            self.pa.remove(self.pa[-1])    def viewarray(self):        print self.paif __name__=='__main__':    pa = PerlArray([1,2,3,4])    pa.viewarray()    pa.shift()    pa.viewarray()    pa.unshift(1)    pa.viewarray()    pa.push(5)    pa.viewarray()    pa.pop()    pa.viewarray()
13-11.电子商务。

你需要为一家B2C零售商编写一个基础的电子商务引擎。你需要写一个针对顾客的类User,一个对应存货清单的类Item,还有一个对应购物车的类叫Cart。货物放到购物车里,顾客可以有多个购物车。同时购物车里可以有多个货物,包括多个同样的货物。

class Item(object):    def __init__(self,product,price):        self.product = product        self.price = price    def __str__(self):        return '(%s, %.2f)' %(self.product,self.price)        class Cart(object):    def __init__(self,name):        self.name = name        self.cartlist = {}    def showcart(self):        for c in self.cartlist:            print self.name,c,self.cartlist[c]    def appenditem(self,item,count=1):        if item not in self.cartlist:            self.cartlist[item] = count        else:            self.cartlist[item] += count    def deleteitem(self,item,count=1):        if (item in self.cartlist) and self.cartlist[item]>=count:            self.cartlist[item] -= count        if self.cartlist[item] == 0:            self.cartlist.pop(item)class User(object):    def __init__(self,name):        self.name = name        self.userdb = []    def showuser(self):        print self.name,self.userdb    def appendcart(self,cart):        self.userdb.append(cart.name)    def deletecart(self,cart):        self.userdb.remove(cart.name)if __name__=='__main__':    i1 = Item('television',4999)    i2 = Item('cellphone',1999)    print i1,i2    c1 = Cart('cart1')    c2 = Cart('cart2')    c3 = Cart('cart3')    c1.appenditem(i1,1)    c1.appenditem(i2,1)    c2.appenditem(i2,2)    c3.appenditem(i1,2)    c1.showcart()    c2.showcart()    c3.showcart()    u1 = User('Tom')    u2 = User('Jerry')    u1.appendcart(c1)    u2.appendcart(c2)    u2.appendcart(c3)    u1.showuser()    u2.showuser()
13-12.聊天室。

你需要三个类:一个Message类,它包含一个消息字符串以及诸如广播、单方收件人等其他信息。一个User类,包含了进入你聊天室的某个人的所有信息。一个Room类,它体现了一个更加复杂的聊天系统,用户可以在聊天时创建单独的房间,并邀请其他人加入。

class Message(object):    def __init__(self,msg='',broadcast=False,froms='',to=''):        self.msg = msg        self.broadcast = broadcast        self.froms = froms        self.to = to    def __str__(self):        if self.broadcast:            return 'message: %s from %s send to everyone' %(self.msg,self.froms)        else:            return 'message: %s from %s send to %s' %(self.msg,self.froms,self.to)class User(object):    hear = {'everyone':''}    def __init__(self,name,sex,age):        self.name = name        self.sex = sex        self.age = age    def __del__(self):        User.hear.clear()    def __str__(self):        return 'user:%s ,sex:%s ,age:%d' %(self.name,self.sex,self.age)    def talk(self,to='',msg=''):        if to == 'everyone':            m = Message(msg,True,self.name)            User.hear['everyone'] = m        elif to:            m = Message(msg,False,self.name,to)            User.hear[to] = m        else:            print 'receiver can not be empty'    def hearmsg(self):        if self.name in User.hear:            print User.hear[self.name]        elif User.hear['everyone']:            print User.hear['everyone']        else:            print 'no msg for %s' %self.name    def talkroom(self,room,to='',msg=''):        if to == 'everyone':            m = Message(msg,True,self.name)            room.receive(m)                   elif to:            m = Message(msg,False,self.name,to)            room.receive(m)        else:            print 'receiver can not be empty'    def hearroom(self,m):        print 'room %s' %m    def createroom(self,name,count=3):        return Room(name,count)        class Room(object):    def __init__(self,rname,count=3):        self.rname = rname        self.count = count        self.userlist = []    def adduser(self,user):        if len(self.userlist) <= self.count:            self.userlist.append(user)        else:            print 'user number limits'    def receive(self,m):        if m.broadcast:            print 'room %s' %m        else:            for user in self.userlist:                if user.name == m.to:                    user.hearroom(m)                    if __name__=='__main__':    u1 = User('bob','male',33)    u2 = User('jim','female',31)    u3 = User('Tom','female',31)    u1.talk('jim','hello')    u2.hearmsg()    u3.hearmsg()    room1 = u2.createroom('girls',2)    room1.adduser(u2)    room1.adduser(u3)    u2.talkroom(room1,'Tom','hello')    u3.talkroom(room1,'everyone','hello')
13-13. 股票投资组合类。你的数据库中记录了每个公司的名字、股票代码、购买日期、购买价格和持股数量。需要编写的方法包括:添加新代号、删除代号、根据当前价格计算出的YTD或年回报率。

# -*- coding: cp936 -*-class Stock(object):    def __init__(self,sname,smark,buydate,buyprice,buycount):        self.sname = sname        self.smark = smark        self.buydate = buydate        self.buyprice = buyprice        self.buycount = buycount    def __str__(self):        return '%s %s %s %.2f %d' % (self.sname, self.smark, self.buydate, self.buyprice, self.buycount)class Operator(object):    def __init__(self):        self.db = {}            def buy(self,stock):        self.db.setdefault(stock.smark,[stock.sname, stock.smark, stock.buydate, stock.buyprice, stock.buycount])    def sell(self,smark):        self.db.pop(smark,None)    def calYTD(self,stock,curprice,curdate):        holddays = self.IntervalDays(stock.buydate,curdate)        costmoney = stock.buyprice*stock.buycount        curmoney = curprice*stock.buycount        benifit = curmoney-costmoney        if stock.smark in self.db:            print 'YTD of %s is %.2f %%' %(stock.smark,benifit/holddays*365/costmoney*100)        else:            print 'stock %s does not exist' %smark    def showdb(self):        print self.db    def isLeapYear(self,year):        if (year%4==0 and year%100!=0) or (year%400==0):            return True    def IntervalDays(self,str1,str2):        month1 = [0,31,28,31,30,31,30,31,31,30,31,30,31]        month2 = [0,31,29,31,30,31,30,31,31,30,31,30,31]        #假定输入的日期都是正确的且后一个日期比前一个日期大,间隔不超过1年        bdate = str1.split('/')        bdate[0],bdate[1],bdate[2]=int(bdate[0]),int(bdate[1]),int(bdate[2])        edate = str2.split('/')        edate[0],edate[1],edate[2]=int(edate[0]),int(edate[1]),int(edate[2])        if bdate==edate:            return 0        elif bdate[1]==edate[1] and bdate[2]==edate[2]:            return abs(bdate[0]-edate[0])        elif bdate[1]!=edate[1] and bdate[2]==edate[2]:            bdays=0            edays=0            if self.isLeapYear(bdate[2]):                for i in range(1,bdate[1]):                    bdays+=month2[i]                bdays=bdays+bdate[0]                for i in range(1,edate[1]):                    edays+=month2[i]                edays=edays+edate[0]                return abs(edays-bdays)            else:                for i in range(1,bdate[1]):                    bdays+=month1[i]                bdays=bdays+bdate[0]                for i in range(1,edate[1]):                    edays+=month1[i]                edays=edays+edate[0]                return abs(edays-bdays)        elif bdate[2]!=edate[2]:            days=0            for i in range(bdate[2]+1,edate[2]):                if self.isLeapYear(i):                    days+=366                else:                    days+=365            if self.isLeapYear(bdate[2]):                for i in range(bdate[1]+1,13):                    days+=month2[i]                days+=(month2[bdate[1]]-bdate[0])            else:                for i in range(bdate[1]+1,13):                    days+=month1[i]                days+=(month1[bdate[1]]-bdate[0])            if self.isLeapYear(edate[2]):                for i in range(1,edate[1]):                    days+=month2[i]                days+=edate[0]                return days            else:                for i in range(1,edate[1]):                    days+=month1[i]                days+=edate[0]                return dayss1 = Stock('xx','123','01/01/2016',1.0,1000)s2 = Stock('yy','234','05/01/2016',18.0,1000)op1 = Operator()op1.buy(s1)op1.buy(s2)op1.showdb()op1.sell('234')op1.showdb()op1.calYTD(s1,1.01,'31/01/2016')
13-14.DOS。为DOS机器编写一个Unix操作界面的shell。你向用户提供一个命令行,使得用户可以在那里输入unix命令,你可以对这些命令进行解释,并把返回相应的输出。
import osclass Shell(object):    def __init__(self):        self.cmds = {'ls':'dir','more':'more','cat':'type','cp':'copy','mv':'ren','rm':'del'}    def translate(self,cmd):        opt = cmd.split()        if opt[0] in self.cmds:            opt[0] = self.cmds[opt[0]]        return ' '.join(opt)    def start(self):        while 1:            cmd = raw_input('#')            cmd = self.translate(cmd)            if cmd == 'exit':                break            else:                output = os.popen(cmd).readlines()                for out in output:                    print out,if __name__ == '__main__':    s = Shell()    s.start()
13-16.授权和函数编程。
(a)请为示例中的CanOpen类编写一个writelines()方法,这个新函数可以一次读入多行文本,然后将文本转化为大写的形式。
(b)在writelines()方法中添加一个参数,用这个参数来指明是否需要为每行文本加上一个换行符。此参数的默认值是False,表示不加换行符。

import osclass CapOpen(object):    def __init__(self,fn,mode='r',buf=-1):        self.file = open(fn,mode,buf)    def __str__(self):        return str(self.file)    def __repr__(self):        return `self.file`    def write(self,line):        self.file.write(line.upper())    def writelines(self,lines,enter=False):        for eachline in lines:            if enter:                eachline += os.linesep            self.write(eachline)    def __getattr__(self,attr):        return getattr(self.file,attr)if __name__ == '__main__':    f1 = CapOpen('d:\\1.txt','r')    content = f1.readlines()    f1.close    f2 = CapOpen('d:\\2.txt','w')    f2.writelines(content,False)    f2.close()
13-17. 数值类型子类化。在示例13.3中所看到的moneyfmt.py脚本基础上修改它,使得它可以扩展Python的浮点类型。请确保它支持所有操作,而且是不可变的。

#因为__new__实例化的是不可变对象,所以不需要实现update方法class MoneyFmt(float):    def __new__(cls,value=0.0,flag='-'):        cls.flag = flag        cls.mvalue = super(MoneyFmt,cls).__new__(cls,value)        return cls.mvalue            def dollarize(cls):        val = round(cls.mvalue,2)        strvalue = str(val)        pos = strvalue.find('.')        while (pos-3)>0:            strvalue = strvalue[:pos-3]+','+strvalue[pos-3:]            pos -= 3        if strvalue.startswith('-'):            return cls.flag+'$'+strvalue[1:]        else:            return '$'+strvalue                def __nonzero__(cls):        if (cls.mvalue == 0):            return False        else:            return True            def __str__(cls):        return cls.dollarize()
13-18. 序列类型子类化。模仿前面练习13-4中的用户注册类的解决方案,编写一个子类。要求允许用户修改密码,但密码有效期是12个月,过期后不能重复使用。

from datetime import datetimeimport cPickle,osclass userlist(list):    def __init__(self,dbfile,valid=4380):        list.__init__([])        self.valid = valid        if os.path.exists(dbfile):            f = file(dbfile)            self.extend(cPickle.load(f))            f.close()        self.dbfile = dbfile        self.flag = False    def save(self):        f = file(self.dbfile, 'w')          cPickle.dump(self, f)          f.close()    def login(self,user,pwd):        for i in range(len(self)):            if self[i][0] == user and self[i][1] == pwd:                dn = datetime.now().date()                dr = self[i][2].date()                if (dn - dr).days > self.valid:                    print 'your pwd is expired,pls ask admin to change it'                    self.flag = False                    break                else:                    self.flag = True                    break            else:                continue    def deluser(self,num):        if self.flag:            self.pop(num)        else:            print 'login first'    def updateuser(self,user,pwd):        if self.flag:            self.append([user,pwd,datetime.now()])                    else:            print 'login first'    def modifypwd(self,user,pwd):        if self.flag:            for i in range(len(self)):                if self[i][0] == user:                    self[i][1] = pwd                    self[i][2] = datetime.now()    def listall(self):        if self.flag:            print self        else:            print 'login first'if __name__=='__main__':    user = userlist("cPickle.dat")    user.login('root','root')    user.listall()    user.modifypwd('test2','test3')    user.save()    user.listall()
13-19. 映射类型子类化。

class SortedKeyDict(dict):    def skeys(self):        return sorted(self.keys())if __name__ == '__main__':    d = SortedKeyDict((('zheng-cai',67),('hui-jun',68),('xin-yi',2)))    print 'By iterator:'.ljust(12), [key for key in d]    print 'By keys():'.ljust(12), d.skeys()

13-20.类的定制。改进脚本time60.py
(a)允许“空”实例化:如果小时和分钟的值没有给出,默认为0小时0分钟。
(b)用0占位组成两位数的形式,因为当前的时间格式不符合要求。
(c)除了用hours(hr)和minutes(min)进行初始化外,还支持以下时间输入格式:
一个由小时和分钟组成的元组,如(10,30)
一个由小时和分钟组成的字典,如{'hr':10, 'min':30}
一个代表小时和分钟的字符串,如"10:30"
(e)实现__repr__()。
(f)添加60进制的运算功能。

class Time60(object):    def __init__(self, hr=0, min=0):        if isinstance(hr,str):            tmp = hr.split(':')            self.hr = int(tmp[0])            self.min = int(tmp[1])        else:            self.hr = hr            self.min = min    def __str__(self):        return "%02d:%02d" % (self.hr, self.min)    def __repr__(self):        return repr("%02d:%02d" % (self.hr, self.min))    def __add__(self, other):        hr = self.hr + other.hr        min = self.min + other.min        ahr = min // 60        min %= 60        hr += ahr        return self.__class__(hr, min)    def __iadd__(self, other):        self.hr += other.hr        self.min += other.min        return selfif __name__ == '__main__':    print Time60()    print Time60(12, 5)    print Time60(*(10,30))    print Time60(**{'hr':10,'min':30})    print Time60("10:30")    print Time60("12:5")    print `Time60('12:05')`    print Time60(10, 30)+Time60(8, 45)















0 0
原创粉丝点击