13-3.对类进行定制。写一个类,用来将浮点型值转换为金额。
 1 class MoneyFmt(object):
 2 
 3     def __init__(self, value=0.0, flag='-'):
 4 
 5         self.value = float(value)
 6         self.flag = flag
 7 
 8     def dollarize(self):
 9         """转换"""
10         val = round(self.value, 2)
11         strvalue = str(val)
12         if strvalue.startswith('-'):
13             strvalue = strvalue[1:]
14             len = strvalue.find('.')
15             while (len-3) > 0:
16                 strvalue = strvalue[:len-3] + ',' + strvalue[len-3:]
17                 len -= 3
18             return self.flag + '$' + strvalue
19 
20         len = strvalue.find('.')
21         while (len-3) > 0:
22             strvalue = strvalue[:len-3] + ',' + strvalue[len-3:]
23             len -= 3
24         return '$' + strvalue
25 
26     def update(self, newvalue=None):
27         """更新"""
28         if newvalue is not None:
29             self.value = float(newvalue)
30 
31     def __nonzero__(self):
32         "非零"
33         if self.value == 0:
34             return False
35         return True
36 
37     def __str__(self):
38         return self.dollarize()
39 
40     def __repr__(self):
41         return repr(self.value)

13-4.用户注册。

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

 1 from datetime import datetime
 2 import shelve
 3 
 4 class Userdatabase(object):
 5 
 6     def __init__(self, dbfile):
 7         """创建数据库"""
 8         self.dbfile = dbfile
 9         self.db = shelve.open(self.dbfile, 'c')
10         self.db.close()
11 
12     def newuser(self, user, pwd):
13         """注册"""
14         self.db = shelve.open(self.dbfile, 'r')
15         if user in self.db:
16             print("User already exists")
17         self.db = shelve.open(self.dbfile, 'c')
18         self.db[user] = [user, pwd, datetime.now()]
19         self.db.close()
20         self.flag = False
21 
22     def login(self, user, pwd):
23         """登录"""
24         self.db = shelve.open(self.dbfile, 'r')
25         if user not in self.db:
26             self.flag = False
27         elif self.db[user][1] == pwd:
28             self.flag = True
29         self.db.close()
30 
31     def deluser(self, user):
32         """删除"""
33         self.db = {}
34         if self.flag:
35             self.db = shelve.open(self.dbfile, 'r')
36             if user in self.db:
37                 self.db.pop(user)
38         else:
39             print('login first')
40 
41     def updateuser(self, user, pwd):
42         """更新"""
43         if self.flag:
44             self.db = shelve.open(self.dbfile, 'c')
45             self.db[user] = [user, pwd, datetime.now()]
46             self.db[user] = self.db[user]
47         else:
48             print('login first')
49 
50     def listall(self):
51         """查看"""
52         if self.flag:
53             for user in self.db:
54                 print(self.db[user][0], self.db[user][1])
55         else:
56             print('login first')
57 
58 if __name__ == '__main__':
59     user = Userdatabase('shelve.data')
60     user.newuser('admin', '123456')
61     user.login('admin', '123456')
62     user.updateuser('admin', '123456')
63     user.updateuser('test', '123456')
64     user.listall()
65     user.deluser('test')
66     user.listall()

13-5.几何。创建一个由有序数值对(x,y)组成的Point类,代表某个点的X和Y坐标。

 1 class Point(object):
 2 
 3     def __init__(self, x=0, y=0):
 4         self.x = x
 5         self.y = y
 6 
 7     def __str__(self):
 8         return '(%d, %d)' % (self.x, self.y)
 9 
10 if __name__ == '__main__':
11     p = Point(1, 1)
12     print(p)

13-6.几何。创建一个直线类,除主要属性:一对坐标值外,它还具有长度和斜线属性。你需要覆盖__repr__()方法,使得代表那条直线的字符串表示形式是由一对元组构成的元组。

 1 from math import sqrt
 2 
 3 class Beeline(object):
 4 
 5     def __init__(self, x1=0, y1=0, x2=0, y2=2):
 6         self.x1 = x1
 7         self.y1 = y1
 8         self.x2 = x2
 9         self.y2 = y2
10         self.length = 0
11         self.slope = None
12 
13     def getLength(self):
14         """长度"""
15         if self.x1 == self.x2 and self.y1 == self.y2:
16             self.length = 0
17         elif self.x1 == self.x2:
18             self.length = abs(self.y2 - self.y1)
19         elif self.y1 == self.y2:
20             self.length = abs(self.x2 - self.x1)
21         else:
22             self.length = sqrt((self.y2 - self.y1)**2 + (self.x2 - self.x1)**2)
23         return self.length
24 
25     def getSlope(self):
26         """斜率"""
27         if self.length == 0:
28             self.slope = None
29         elif self.x1 == self.x2 or self.y1 == self.y2:
30             self.slope = None
31         else:
32             self.slope = float(self.y2 - self.y1) / (self.x2 - self.x1)
33         return self.slope
34 
35     def __str__(self):
36         return '((%d, %d),(%d, %d))' % (self.x1, self.y1, self.x2, self.y2)
37 
38     __repr__ = __str__
39 
40 if __name__ == '__main__':
41     b = Beeline(1, 2, 3, 4)
42     print(b)
43     print('Length is %f' % b.getLength())
44     print('Slope is %s' % b.getSlope())

13-7.数据类。提供一个time模块的接口,允许用户按照自己给定的时间格式来查看日期。你的类应该维护一个日期值,并用给定的时间创建一个实例,如果没有给出时间值,程序执行时会默认采用当前的系统时间。

 1 import time
 2 
 3 class TimeFormat(object):
 4 
 5     def __init__(self, t=time.time()):
 6         self.mytime = t
 7 
 8     def update(self, t=time.time()):
 9         self.mytime = t
10 
11     def display(self, ft=None):
12         fmt = {}
13         fmt['MDY'] = '%m/%d/%y'
14         fmt['MDYY'] = '%m/%d/%Y'
15         fmt['DMY'] = '%d/%m/%y'
16         fmt['DMYY'] = '%d/%m/%Y'
17         fmt['MODYY'] = '%b %d,%Y'
18         if ft in fmt:
19             return (time.strftime(fmt[ft], time.localtime(self.mytime)))
20         return time.ctime(self.mytime)
21 
22 if __name__ == '__main__':
23     tf = TimeFormat()
24     print(tf.display())
25     print(tf.display('MDY'))
26     print(tf.display('MDYY'))
27     print(tf.display('DMY'))
28     print(tf.display('DMYY'))
29     print(tf.display('MODYY'))
30     tf.update(time.time() + 60)
31     print(tf.display())

 13-8.堆栈类。

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

 1 class Stack(object):
 2 
 3     def __init__(self, l=[]):
 4         self.l = l
 5 
 6     def isempty(self):
 7         if len(self.l) == 0:
 8             return 1
 9         return 0
10 
11     def push(self, element):
12         print('pushed [', element, ']')
13         self.l.append(element)
14 
15     def peek(self):
16         if self.isempty():
17             print('can not peek from an empty stack')
18         return self.l[0]
19 
20     def pop(self):
21         if self.isempty():
22             print('can not pop from an empty stack')
23         else:
24             print('removed [', self.l.pop(), ']')
25 
26     def viewstack(self):
27         print(self.l)
28 
29 if __name__ == '__main__':
30     s = Stack()
31     s.viewstack()
32     s.pop()
33     s.viewstack()
34     s.push(2)
35     s.viewstack()

 13-9.队列类。实现一个队列类,这个类必须支持下面几种方法:enqueue()在队列的尾部加入一个新的元素,dequeue()在队列的头部取出一个元素,返回它并且把它从列表中删除。

 1 class Queue(object):
 2 
 3     def __init__(self, l=[]):
 4         self.l = l
 5 
 6     def enqueue(self, element):
 7         print('enter queue [', element, ']')
 8         self.l.append(element)
 9 
10     def dequeue(self):
11         if self.l:
12             print('removed [', self.l.pop(0), ']')
13         else:
14             print('can not pop from an empty stack')
15 
16     def viewstack(self):
17         print(self.l)
18 
19 if __name__ == '__main__':
20     q = Queue([1, 2, 3])
21     q.viewstack()
22     q.enqueue(4)
23     q.dequeue()
24     q.viewstack()

13-10.堆栈和队列。编写一个类,定义一个能够同时具有堆栈和队列操作行为的数据结构。这个类和Perl语言中数组相像。需要实现四个方法。

 1 class FifoLifo(object):
 2 
 3     def __init__(self, l=[]):
 4         self.l = l
 5 
 6     def shift(self):
 7         """删除头"""
 8         if self.l:
 9             print('removed [', self.l.pop(0), ']')
10         else:
11             print('can not pop from an empty stack')
12 
13     def unshift(self, element):
14         """插入头"""
15         print('inserted [', element, ']')
16         self.l.insert(0, element)
17 
18     def push(self, element):
19         """插入尾"""
20         print('pushed [', element, ']')
21         self.l.append(element)
22 
23     def pop(self):
24         """删除尾"""
25         if self.l:
26             print('removed [', self.l.pop(), ']')
27         else:
28             print('can not pop from an empty stack')
29 
30     def viewstack(self):
31         print(self.l)
32 
33 if __name__ == '__main__':
34     f = FifoLifo([1, 2, 3, 4, 5])
35     f.viewstack()
36     f.shift()
37     f.unshift(6)
38     f.push(0)
39     f.pop()
40     f.viewstack()

 13-11.电子商务。

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

 1 class Item(object):
 2     """物品价格清单"""
 3     def __init__(self, product, price):
 4         self.product = product
 5         self.price = price
 6 
 7     def __str__(self):
 8         return '(%s, %.2f)' % (self.product, self.price)
 9 
10 class Cart(object):
11     """购物车"""
12     def __init__(self, cartname):
13         self.cartname = cartname
14         self.cartlist = {}
15 
16     def appenditem(self, item, count=1):
17         """增加数量"""
18         if item not in self.cartlist:
19             self.cartlist[item] = count
20         else:
21             self.cartlist[item] += count
22 
23     def showcart(self):
24         """查看"""
25         for i in self.cartlist:
26             print(self.cartname, i, self.cartlist[i])
27 
28     def deleteitem(self, item, count=1):
29         """减少数量"""
30         if item in self.cartlist and self.cartlist[item]>=count:
31             self.cartlist[item] -= count
32         if self.cartlist[item] == 0:
33             self.cartlist.pop(item)
34 
35 class User(object):
36     """顾客"""
37     def __init__(self, name):
38         self.name = name
39         self.userdb = []
40 
41     def appendcart(self, cart):
42         self.userdb.append(cart.cartname)
43 
44     def showuser(self):
45         print(self.name, self.userdb)
46 
47 if __name__ == '__main__':
48     i1 = Item('huawei', 15000)
49     i2 = Item('iphone', 7000)
50     print(i1, i2)
51     c1 = Cart('cart1')
52     c2 = Cart('cart2')
53     c3 = Cart('cart3')
54     c1.appenditem(i1, 1)
55     c1.appenditem(i2, 1)
56     c2.appenditem(i2, 2)
57     c3.appenditem(i1, 2)
58     c1.showcart()
59     c2.showcart()
60     c3.showcart()
61     u1 = User('Tom')
62     u2 = User('Jerry')
63     u1.appendcart(c1)
64     u2.appendcart(c2)
65     u2.appendcart(c3)
66     u1.showuser()
67     u2.showuser()

 13-12.聊天室。

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

  1 class Message(object):
  2 
  3     def __init__(self, msg='', broadcast=False, froms='', to=''):
  4 
  5         self.msg = msg
  6         self.broadcast = broadcast
  7         self.froms = froms
  8         self.to = to
  9 
 10     def __str__(self):
 11         """广播"""
 12         if self.broadcast:
 13             return 'message: %s from %s send to everyone' % (self.msg, self.froms)
 14         else:
 15             return 'message: %s from %s send to %s' % (self.msg, self.froms, self.to)
 16 
 17 
 18 class User(object):
 19 
 20     hear = {'everyone': ''}
 21 
 22     def __init__(self, name, sex, age):
 23 
 24         self.name = name
 25         self.sex = sex
 26         self.age = age
 27 
 28     def __del__(self):
 29 
 30         User.hear.clear()
 31 
 32     def __str__(self):
 33 
 34         return 'user:%s ,sex:%s ,age:%d' % (self.name, self.sex, self.age)
 35 
 36     def talk(self, to='', msg=''):
 37         """发送广播"""
 38         if to == 'everyone':
 39             m = Message(msg, True, self.name)
 40             User.hear['everyone'] = m
 41         elif to:
 42             m = Message(msg, False, self.name, to)
 43             User.hear[to] = m
 44         else:
 45             print('receiver can not be empty')
 46 
 47     def hearmsg(self):
 48         """显示消息"""
 49         if self.name in User.hear:
 50             print(User.hear[self.name])
 51         elif User.hear['everyone']:
 52             print(User.hear['everyone'])
 53         else:
 54             print('no msg for %s' % self.name)
 55 
 56     def talkroom(self, room, to='', msg=''):
 57         """room广播"""
 58         if to == 'everyone':
 59             m = Message(msg, True, self.name)
 60             room.receive(m)
 61         elif to:
 62             m = Message(msg, False, self.name, to)
 63             room.receive(m)
 64         else:
 65             print('receiver can not be empty')
 66 
 67     def hearroom(self, m):
 68         """显示room消息"""
 69         print('room %s' % m)
 70 
 71     def createroom(self, name, count=3):
 72         """room人员"""
 73         return Room(name, count)
 74 
 75 
 76 class Room(object):
 77 
 78     def __init__(self, rname, count=3):
 79 
 80         self.rname = rname
 81         self.count = count
 82         self.userlist = []
 83 
 84     def adduser(self, user):
 85         """room用户邀请"""
 86         if len(self.userlist) <= self.count:
 87             self.userlist.append(user)
 88         else:
 89             print('user number limits')
 90 
 91     def receive(self, m):
 92         """room广播"""
 93         if m.broadcast:
 94             print('room %s' % m)
 95         else:
 96             for user in self.userlist:
 97                 if user.name == m.to:
 98                     user.hearroom(m)
 99 
100 
101 if __name__ == '__main__':
102     u1 = User('bob', 'male', 33)
103     u2 = User('jim', 'female', 31)
104     u3 = User('Tom', 'female', 31)
105     u1.talk('jim', 'hello')
106     u2.hearmsg()
107     u3.hearmsg()
108     room1 = u2.createroom('girls', 2)
109     room1.adduser(u2)
110     room1.adduser(u3)
111     u2.talkroom(room1, 'Tom', 'hello')
112     u3.talkroom(room1, 'everyone', 'hello')

 13-13. 股票投资组合类。你的数据库中记录了每个公司的名字、股票代码、购买日期、购买价格和持股数量。需要编写的方法包括:添加新代号、删除代号、根据当前价格计算出的YTD或年回报率。

  1 class Stock(object):
  2 
  3     def __init__(self, name, code, date, price, amount):
  4 
  5         self.name = name
  6         self.code = code
  7         self.date = date
  8         self.price = price
  9         self.amount = amount
 10 
 11     def __str__(self):
 12         return '%s %s %s %.2f %d' % (self.name, self.code, self.date, self.price, self.amount)
 13 
 14 class Operator(object):
 15 
 16     def __init__(self):
 17         
 18         self.db = {}
 19 
 20     def newcode(self, stock):
 21         
 22         self.db.setdefault(stock.code, [stock.name, stock.date, stock.price, stock.amount])
 23 
 24     def popcode(self, code):
 25         
 26         self.db.pop(code)
 27 
 28     def years(self, year):
 29         
 30         if (year % 4 == 0 and year % 100 != 0) or (year % 4 == 0 and year % 400 == 0):
 31             return True
 32 
 33     def months(self, str1, str2):
 34         
 35         month1 = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
 36         month2 = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
 37         bdate = str1.split('/')
 38         bdate[0], bdate[1], bdate[2] = int(bdate[0]), int(bdate[1]), int(bdate[2])
 39         edate = str2.split('/')
 40         edate[0], edate[1], edate[2] = int(edate[0]), int(edate[1]), int(edate[2])
 41         
 42         if bdate == edate:
 43             return 0
 44         
 45         elif bdate[1] == edate[1] and bdate[2] == bdate[2]:
 46             return abs(bdate[0]-edate[0])
 47         
 48         elif bdate[1] != edate[1] and bdate[2] == edate[2]:
 49             bdays = 0
 50             edays = 0
 51             if self.years(bdate[2]):
 52                 for i in range(1, bdate[1]):
 53                     bdays += month2[i]
 54                 bdays = bdays + bdate[0]
 55                 for i in range(1, edate[1]):
 56                     edays += month2[i]
 57                 edays = edays + edate[0]
 58                 return abs(edays - bdays)
 59             else:
 60                 for i in range(1, bdate[1]):
 61                     bdays += month1[i]
 62                 bdays = bdays + bdate[0]
 63                 for i in range(1, edate[1]):
 64                     edays += month1[i]
 65                 edays = edays + edate[0]
 66                 return abs(edays - bdays)
 67             
 68         elif bdate[2] != edate[2]:
 69             days = 0
 70             for i in range(bdate[2]+1, edate[2]):
 71                 if self.years(i):
 72                     days += 366
 73                 else:
 74                     days += 365
 75             if self.years(bdate[2]):
 76                 for i in range(bdate[1]+1, 13):
 77                     days += month2[i]
 78                 days += (month2[bdate[1]]-bdate[0])
 79             else:
 80                 for i in range(bdate[1]+1, 13):
 81                     days += month1[i]
 82                 days += (month1[bdate[1] - bdate[0]])
 83             if self.years(edate[2]):
 84                 for i in range(1, edate[1]):
 85                     days += month2[i]
 86                 days += edate[0]
 87                 return days
 88             else:
 89                 for i in range(1, edate[1]):
 90                     days += month1[i]
 91                 days += edate[0]
 92                 return days
 93 
 94     def YTD(self, stock, newprice, newdate):
 95 
 96         holddays = self.months(stock.date, newdate)
 97         costmoney = stock.price * stock.amount
 98         curmoney = newprice * stock.amount
 99         benifit = curmoney - costmoney
100         
101         if stock.code in self.db:
102             print('YTD of %s is %.2f %%' %(stock.code, benifit/holddays*365/costmoney))
103         else:
104             print('Stock %s does not exists' % stock.code)
105 
106     def showdb(self):
107         print(self.db)
108 
109 s1 = Stock('xx', '123', '01/01/2019', 1.0, 1000)
110 s2 = Stock('yy', '234', '05/01/2019', 18.0, 1000)
111 op1 = Operator()
112 op1.newcode(s1)
113 op1.newcode(s2)
114 op1.showdb()
115 op1.popcode('234')
116 op1.showdb()
117 op1.YTD(s1, 1.01, '11/03/2019')

 13-14.DOS。为DOS机器编写一个Unix操作界面的shell。你向用户提供一个命令行,使得用户可以在那里输入unix命令,你可以对这些命令进行解释,并把返回相应的输出。

 1 import os
 2 
 3 class Shell(object):
 4 
 5     def __init__(self):
 6 
 7         self.cmddict = {'ls': 'dir', 'more': 'more', 'cat': 'type', 'cp': 'copy', 'mv': 'ren', 'rm': 'del'}
 8 
 9     def translate(self, cmd):
10 
11         opt = cmd.split()
12         if opt[0] in self.cmddict:
13             opt[0] = self.cmddict[opt[0]]
14         return ' '.join(opt)
15 
16     def start(self):
17 
18         while True:
19             cmd = input('#')
20             cmd = self.translate(cmd)
21             if cmd == 'exit':
22                 break
23 
24             output = os.popen(cmd).readlines()
25             for out in output:
26                 print(out)
27 
28 if __name__ == '__main__':
29     s = Shell()
30     s.start()

13-16.授权和函数编程。
(a)请为示例中的CanOpen类编写一个writelines()方法,这个新函数可以一次读入多行文本,然后将文本转化为大写的形式。
(b)在writelines()方法中添加一个参数,用这个参数来指明是否需要为每行文本加上一个换行符。此参数的默认值是False,表示不加换行符。

 1 import os
 2 
 3 class CapOpen(object):
 4 
 5     def __init__(self, fn, mode='r', buf=-1):
 6         
 7         self.file = open(fn, mode, buf)
 8 
 9     def __str__(self):
10         
11         return str(self.file)
12 
13     def __repr__(self):
14         
15         return 'self.file'
16 
17     def write(self, line):
18         
19         self.file.write(line.upper())
20 
21     def writelines(self, lines, enter=False):
22         
23         for line in lines:
24             if enter:
25                 line += os.linesep
26             self.write(line)
27 
28     def __getattr__(self, attr):
29         
30         return getattr(self.file, attr)
31 
32 if __name__ == '__main__':
33     f1 = CapOpen('test.txt')
34     lines = f1.readlines()
35     f1.close()
36 
37     f2 = CapOpen('newtest.txt', 'w')
38     f2.writelines(lines, False)
39     f2.close()

 13-17. 数值类型子类化。在示例13.3中所看到的moneyfmt.py脚本基础上修改它,使得它可以扩展Python的浮点类型。请确保它支持所有操作,而且是不可变的。

 1 class MoneyFmt(float):
 2 
 3     def __new__(cls, value=0.0, flag='-'):
 4 
 5         cls.flag = flag
 6         cls.value = super(MoneyFmt, cls).__new__(cls, value)
 7         return cls.value
 8 
 9     def dollarize(cls):
10         """转换"""
11         val = round(cls.value, 2)
12         strvalue = str(val)
13         if strvalue.startswith('-'):
14             strvalue = strvalue[1:]
15             len = strvalue.find('.')
16             while (len-3) > 0:
17                 strvalue = strvalue[:len-3] + ',' + strvalue[len-3:]
18                 len -= 3
19             return cls.flag + '$' + strvalue
20 
21         len = strvalue.find('.')
22         while (len-3) > 0:
23             strvalue = strvalue[:len-3] + ',' + strvalue[len-3:]
24             len -= 3
25         return '$' + strvalue
26 
27     def __nonzero__(cls):
28         "非零"
29         if cls.value == 0:
30             return False
31         return True
32 
33     def __str__(cls):
34 
35         return cls.dollarize()
36 
37 
38 if __name__ == '__main__':
39     money = input('Money: ')
40     moneyfmt = MoneyFmt(money)
41     print(moneyfmt.dollarize())

13-18. 序列类型子类化。模仿前面练习13-4中的用户注册类的解决方案,编写一个子类。要求允许用户修改密码,但密码有效期是12个月,过期后不能重复使用。

 1 import time, shelve
 2 
 3 class Userdatabase(object):
 4 
 5     def __init__(self, dbfile):
 6         """创建数据库"""
 7         self.dbfile = dbfile
 8         self.db = shelve.open(self.dbfile, 'c')
 9         self.db.close()
10 
11     def newuser(self, user, pwd):
12         """注册"""
13 
14         self.db = shelve.open(self.dbfile, 'r')
15         if user in self.db:
16             print("User already exists")
17         self.db = shelve.open(self.dbfile, 'c')
18         self.db[user] = [user, [pwd, time.time()], time.ctime()]
19         self.db.close()
20         self.flag = False
21 
22     def login(self, user, pwd):
23         """登录"""
24         self.db = shelve.open(self.dbfile, 'r')
25         if user not in self.db:
26             self.flag = False
27         elif self.db[user][1][0] == pwd:
28             if self.db[user][1][-1] - time.time() > 365*24*60*60:
29                 print("Password has expired")
30                 self.flag = False
31             else:
32                 self.flag = True
33         self.db.close()
34 
35     def deluser(self, user):
36         """删除"""
37         self.db = {}
38         if self.flag:
39             self.db = shelve.open(self.dbfile, 'r')
40             if user in self.db:
41                 self.db.pop(user)
42         else:
43             print('login first')
44 
45     def updateuser(self, user, pwd):
46         """更新密码"""
47         newdb = {}
48         if self.flag:
49             self.db = shelve.open(self.dbfile, 'r')
50             if pwd in self.db[user][1]:
51                 print("The new password cannot be the same as the used password")
52             else:
53                 value = [user, self.db[user][1], time.ctime()]
54                 value[1].insert(0, pwd)
55                 value[1][-1] = time.time()
56                 newdb[user] = value
57                 self.db = shelve.open(self.dbfile, 'c')
58                 self.db[user] = newdb[user]
59                 print(self.db[user])
60         else:
61             print('login first')
62 
63 
64     def listall(self):
65         """查看"""
66         if self.flag:
67             for user in self.db:
68                 print(self.db[user][0], self.db[user][1][0])
69         else:
70             print('login first')
71 
72 if __name__ == '__main__':
73     user = Userdatabase('shelve.data')
74     user.newuser('admin', '123456')
75     user.newuser('test', '123456')
76     user.login('admin', '123456')
77     user.login('test', '123456')
78     user.updateuser('admin', '123456')
79     user.updateuser('test', '123456')
80     user.listall()
81     user.deluser('test')
82     user.listall()

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进制的运算功能。

 1 class Time60(object):
 2     'Time60 - track hours and minutes'
 3 
 4     def __init__(self, *time):
 5         'Time60 constructor - takes hours and minutes'
 6         if len(time) == 1:
 7             if type(time[0]) == tuple:
 8                 self.hr = time[0][0]
 9                 self.min = time[0][1]
10             elif type(time[0]) == dict:
11                 self.hr = time[0]['hr']
12                 self.min = time[0]['min']
13             elif type(time[0]) == str:
14                 all = time[0].split(':')
15                 self.hr = int(all[0])
16                 self.min = int(all[1])
17 
18         elif len(time) == 0:
19             self.hr = 0
20             self.min = 0
21 
22         else:
23             self.hr = time[0]
24             self.min = time[1]
25 
26     def __str__(self):
27         'Time60 - string representation'
28         return '%02d:%02d' % (self.hr, self.min)
29 
30     def __repr__(self):
31 
32         return repr('%02d:%02d' % (self.hr, self.min))
33 
34     def __add__(self, other):
35         'Time60 - overloading the addition operator'
36         hr = self.hr + other.hr
37         min = self.min + other.min
38         ahr = min // 60
39         min %= 60
40         hr += ahr
41         if hr > 23: hr = 0
42         return self.__class__(hr, min)
43 
44     def __iadd__(self, other):
45         'Time60 - overloading in-place addition'
46         self.hr += other.hr
47         self.min += other.min
48         return self
49 
50 print(Time60())
51 print(Time60(10, 30))
52 print(Time60("15:31"))
53 print(Time60((10, 30)))
54 print(Time60({'hr':11, 'min':15}))
55 print(Time60(1, 5))
56 print(Time60("15:31") + Time60(8,31))

 

posted on 2019-03-12 16:26  詼詼  阅读(625)  评论(0编辑  收藏  举报