《Python核心程式設計》第13章 面向物件程式設計 練習
13-3.對類進行定製。
寫一個類,用來將浮點型值轉換為金額。
13-4.使用者註冊。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-5.幾何。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])
建立一個由有序數值對(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)