《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 p13-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
- 《Python核心编程》第13章 习题
- 《Python核心编程》第2章 习题
- 《Python核心编程》第3章 习题
- 《Python核心编程》第5章 习题
- 《Python核心编程》第6章 习题
- 《Python核心编程》第7章 习题
- 《Python核心编程》第8章 习题
- 《Python核心编程》第9章 习题
- 《Python核心编程》第10章 习题
- 《Python核心编程》第11章 习题
- 《Python核心编程》第12章 习题
- 《Python核心编程》第6章 习题
- 《Python核心编程》第7章 习题
- 《Python核心编程》第7章 习题
- 《Python核心编程》第9章 习题
- 《Python核心编程》第12章 习题
- 《Python核心编程》第14章 习题
- python核心编程第12章习题
- nodejs 表格分页工具类
- 彻底了解指针数组,数组指针,以及函数指针,以及堆中的分配规则
- 11 事件处理
- 浅谈泛型
- 11.1 事件处理基础
- 《Python核心编程》第13章 习题
- MapReduce--Shuffle过程
- 11.2 动作
- Beego初探
- 第14周实践 成绩处理函数版
- 深度优先,广度优先的学习(待续)
- 11.3 鼠标事件
- [ JoyfulPuTTY ] PuTTY开源代码分析.1 --- 全局配置
- 12062