13-3.对类进行定制。
写一个类,用来将浮点型值转换为金额。
class MoneyFmt(object):
def __init__(self, value=0.0):
self.value = float(value)
def update(self, value=None):
if value != None:
self.value = float(value)
def __repr__(self):
return `self.value`
def __str__(self):
pre = '$' if self.value >= 0 else '-$'
return pre + str(round(abs(self.value), 2))
def __nonzero__(self):
return self.value > 0.5
13-4.用户注册。
建立一个用户数据库类,来管理一个系统,该系统要求用户在登录后才能访问某些资源。这个数据库类对用户进行管理,并在实例化操作时加载之前保存的用户信息,提供访问函数来添加或更新数据库的信息。在数据修改后,数据库会在垃圾回收时将新信息保存到磁盘。
import shelve
import os
import time
class UserData(object):
def __init__(self, dbfile):
self._db = {}
if os.path.exists(dbfile):
self._db = shelve.open(dbfile, 'r')
self._dbfile = dbfile
def __del__(self):
data = shelve.open(self._dbfile, 'c')
data.update(self._db)
data.close()
def update(self, name, passwd):
self._db[name] = [passwd, time.time()]
def delete(self, name):
self._db.pop(name)
def login(self, name, passwd):
if self._db.get(name, None)[0] == passwd:
self._db[name][1] = time.time()
return True
return False
def listall(self):
for name in self._db:
print name, self._db[name][0], time.ctime(self._db[name][1])
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)
__repr__ = __str__
13-6.几何。
创建一个直线类,除主要属性:一对坐标值外,它还具有长度和斜线属性。你需要覆盖__repr__()方法,使得代表那条直线的字符串表示形式是由一对元组构成的元组。
from math import sqrt
class Line(object):
def __init__(self, x1=0, y1=0, x2=0, y2=0):
self.p1 = Point(x1, y1)
self.p2 = Point(x2, y2)
def __str__(self):
return '(%s, %s)' % (str(self.p1), str(self.p2))
__repr__ = __str__
def slope(self):
try:
k = float(self.p2.y - self.p1.y) / (self.p2.x - self.p1.x)
except ZeroDivisionError:
k = None
return k
def length(self):
return sqrt((self.p2.y - self.p1.y)**2 + (self.p2.x - self.p1.x)**2)
13-7.数据类。
提供一个time模块的接口,允许用户按照自己给定的时间格式来查看日期。你的类应该维护一个日期值,并用给定的时间创建一个实例,如果没有给出时间值,程序执行时会默认采用当前的系统时间。
import time
class TimeFmt(object):
def __init__(self, time=time.time()):
self.__time = time
def update(self, time=time.time()):
self.__time = time
def display(self, fmt=None):
fmtdb = {}
fmtdb['MDY'] = '%m/%d/%y'
fmtdb['MDYY'] = '%m/%d/%Y'
fmtdb['DMY'] = '%d/%m/%y'
fmtdb['DMYY'] = '%d/%m/%Y'
fmtdb['MODYY'] = '%m %d, %Y'
if fmt in fmtdb:
t = time.localtime(self.__time)
print time.strftime(fmtdb[fmt], t)
else:
print time.ctime(self.__time)
13-8.堆栈类。
实现一个堆栈类,类中应该有push()和pop()方法,还有一个isempty()方法,如果堆栈是空的,返回布尔值1,否则返回0。
class Stack(object):
def __init__(self):
self.__ls = []
def push(self, obj):
self.__ls.append(obj)
def pop(self):
if not self.isempty():
return self.__ls.pop()
def isempty(self):
return len(self.__ls) == 0
def peek(self):
return self.__ls[len(self.__ls)-1]
13-9.队列类。
实现一个队列类,这个类必须支持下面几种方法:enqueue()在队列的尾部加入一个新的元素,dequeue()在队列的头部取出一个元素,返回它并且把它从列表中删除。
class Queue(object):
def __init__(self):
self.__ls = []
def __str__(self):
return str(self.__ls)
def enqueue(self, obj):
self.__ls.append(obj)
def dequeue(self):
if not self.isempty():
return self.__ls.pop(0)
def isempty(self):
return len(self.__ls) == 0
13-11.电子商务。
你需要为一家B2C零售商编写一个基础的电子商务引擎。你需要写一个针对顾客的类User,一个对应存货清单的类Item,还有一个对应购物车的类叫Cart。货物放到购物车里,顾客可以有多个购物车。同时购物车里可以有多个货物,包括多个同样的货物。
class Item(object):
def __init__(self, name, price):
self.name = name
self.price = price
class Cart(object):
def __init__(self):
self.ls = {}
def append(self, item, count):
if item not in self.ls:
self.ls[item] = count
else:
self.ls[item] += count
def delete(self, item, count):
if (item in self.ls) and (self.ls[item] >= count):
self.ls[item] -= count
if self.ls[item] == 0:
self.ls.pop(item)
class User(object):
def __init__(self):
self.ls = []
def append(self, cart):
self.ls.append(cart)
def delete(self, cart):
self.ls.remove(cart)
13-12.聊天室。
你需要三个类:一个Message类,它包含一个消息字符串以及诸如广播、单方收件人等其他信息。一个User类,包含了进入你聊天室的某个人的所有信息。一个Room类,它体现了一个更加复杂的聊天系统,用户可以在聊天时创建单独的房间,并邀请其他人加入。
class Message(object):
def __init__(self, info='', isbroad=False, to='', froms=''):
self.info = info
self.isbroad = isbroad
self.to = to
self.froms = froms
def __str__(self):
if self.isbroad:
msg = '%s say to everone: %s' % (self.froms, self.info)
else:
msg = '%s say to %s: %s' % (self.froms, self.to, self.info)
return msg
class User(object):
def __init__(self, name='', sex=True, age=18):
self.name = name
self.sex = sex
self.age = age
def __str__(self):
return '%s %s %s' % (self.name, self.sex, self.age)
def say(self, room, info, to=''):
if to == '':
msg = Message(info, True, '', self.name)
else:
msg = Message(info, False, to, self.name)
room.receive(msg)
def hear(self, msg):
print msg
def createroom(self, name):
return Room(name)
class Room(object):
def __init__(self, name):
self.name = name
self.userlist = []
def add(self, user):
self.userlist.append(user)
def receive(self, msg):
if msg.isbroad:
print msg
else:
for user in self.userlist:
if user.name == msg.to:
user.hear(msg)
if __name__ == '__main__':
user1 = User('Tom', True, 16)
user2 = User('Lily', False, 15)
user3 = User('Lucy', False)
room = user1.createroom('chatting room')
room.add(user1)
room.add(user2)
room.add(user3)
user1.say(room, 'Hi, Lily', 'Lily')
user2.say(room, 'Hello, Tom', 'Tom')
user3.say(room, 'Hey, you two')
13-14.DOS。
为DOS机器编写一个Unix操作界面的shell。你向用户提供一个命令行,使得用户可以在那里输入unix命令,你可以对这些命令进行解释,并把返回相应的输出。
import os
class Shell(object):
def __init__(self):
self.cmds = {'ls': 'dir', 'cat': 'type', 'rm': 'del'}
def translate(self, cmd):
words = cmd.split()
if words[0] in self.cmds:
words[0] = self.cmds[words[0]]
return ' '.join(words)
def start(self):
while True:
cmd = raw_input('$')
cmd = self.translate(cmd)
if cmd == 'exit':
break
else:
f = os.popen(cmd)
for data in f:
print data,
print
f.close()
if __name__ == '__main__':
sh = Shell()
sh.start()
13-16.授权和函数编程。
(a)请为示例中的CanOpen类编写一个writelines()方法,这个新函数可以一次读入多行文本,然后将文本转化为大写的形式。
(b)在writelines()方法中添加一个参数,用这个参数来指明是否需要为每行文本加上一个换行符。此参数的默认值是False,表示不加换行符。
from os import linesep
class CanOpen(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, newline=False):
for line in lines:
if newline:
line += linesep
self.file.write(line.upper())
def __getattr__(self, attr):
return getattr(self.file, attr)
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):
'Time60 - track hours and minutes'
def __init__(self, hr=0, min=0):
if isinstance(hr, basestring):
t = hr.split(':')
self.hr = int(t[0])
self.min = int(t[1])
else:
self.hr = hr
self.min = min
def __str__(self):
return '%02d:%02d' % (self.hr, self.min)
def __repr__(self):
return "%s('%s')" % (self.__class__.__name__, str(self))
def add60(self, other):
hr = self.hr + other.hr
min = self.min + other.min
carry = min // 60
min %= 60
hr += carry
return (hr, min)
def __add__(self, other):
return self.__class__(*self.add60(other))
def __iadd__(self, other):
(self.hr, self.min) = self.add60(other)
return self
if __name__ == '__main__':
print Time60()
print Time60(12,5)
print Time60(*(10, 30))
print Time60(**{'hr': 10, 'min': 30})
print Time60('10:30')
print `Time60('10:10')`
print Time60(10, 30) + Time60(8, 45)