Python核心编程v2.0 第13章习题(下)

来源:互联网 发布:网络监控软件 免费 编辑:程序博客网 时间:2024/05/22 05:06

13.
大概写了下设想的样式,stock函数中的价格,应该由市场来调用,每日更改。这个地方设成定值,就没写程序验证了。
核心在于用户再去调用当时保存的stock类时,price已经改变就有了利润。
stack类只应该是和这只股票相关的数据。股票当日价格,股票名字,股票id
mystack应保存,用户选的股票,买入的价格,日期,数量这些和股票本身无关的信息
还应该有一个大的类用于更新股票价格。类似市场类

#股票应有一个市场价格,每日变动,这个地方我设成定值3.0class stock(object):    price = 3.0    def __init__(self,name,id):        self.name = name        self.id = id#数据库应该记录的是某个用户手里的股票class mystock(object):    db = []    lirun = 0.0    def add(self,name,id,date,number):        st = stock(name,id)        price = st.price        li = [st,price,date,number]        self.db.append(li)    def sub(self,name,subnum):        for i in self.db:            if i[0].name == name:                i[3] = i[3]-subnum                #获取当前价格,与当时买的价格差价就是利润                self.lirun = (i[0].price - i[1])*subnum + self.lirun    #删除数量为0的股票    def delstock(self):        for i in self.db:            if i[3] == 0 :                self.db.remove(i)

14.
写一个shell 的意思就是,输入的是unix的命令,但是要在DOS的环境下达到该命令想要的效果。
参考了一下网上的答案,在注释部分做了修改,更直接的应该是用os.system就直接对转换过的unix命令进行执行即可

# -*- coding: utf-8 -*-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:                #原博客用的os.popen函数,不是很理解                os.system(cmd)if __name__ == '__main__':    s = Shell()    s.start()

15.
两者是没有差别的,因为在CapOpen中没有覆盖readlines方法。还是调用的file对象提供的。

class 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 __getattr__(self, item):        return getattr(self.file,item)if __name__ == '__main__':    f = CapOpen('ar.txt','r')    print f    lines = f.readlines()    for i in lines:        print i,    f.close()    g = open('ar.txt','r')    print g    lines = g.readlines()    for j in lines:        print j,    g.close()

测试输出

<open file 'ar.txt', mode 'r' at 0x00F9D1D8>Cnna:2828,2017 09 13 10 00Anna:2727,2017 09 13 10 00Bnna:23214,21214<open file 'ar.txt', mode 'r' at 0x00F9DF40>Cnna:2828,2017 09 13 10 00Anna:2727,2017 09 13 10 00Bnna:23214,21214

16.

class 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 __getattr__(self, item):        return getattr(self.file,item)    def writelines(self,list,index = False):        #根据换行标记来设置每行结束是否写换行符        if index == False:            tem = ' '        else:            tem = '\n'        for i in list:            self.file.write(i.upper())            self.file.write(tem)if __name__ == '__main__':    #用列表表示一下多行数据    lines = ['line1','line2','line3','line4']    f = CapOpen('ar.txt','w')    f.writelines(lines)

17.
看网上答案应该是生成一个float类型的子类
没那样写,在moneyfmt.py的基础上改的
在pycharm下运行的,有些就没调试了。
str可以控制 str()以及print语句
repr可以控制repr()和”操作符
比较需要注意的是小数的保留两位并四舍五入的问题。
网上普遍说的round函数和decimal来处理都有问题,这个地方是用的二进制模拟十进制方法来完成的四舍五入。这个处理麻烦了,但是暂时是唯一正确的一种。这种方法需要补充代码,下面写的只是4位小数保留两位的情况。

# -*- coding: utf-8 -*-from __future__ import divisionclass MoneyFmt(object):    def __init__(self,value):        self.value = float(value)    def update(self,value = None):        st = str(value)        index = st.index('.')        st1 = st[:index]        st2 = st[index + 1:]        st3 = st1 + st2        st4 = st3[:-2]        # print st3, st4        yu = int(st3) % 100        if yu >= 5:            sang = int(st4) + 1        else:            sang = int(st4)        re = sang * 10 / 1000        self.value = re        return self.value    def __repr__(self):        return '\''+str(self.value)+'\''    def __str__(self):        if self.value>=0:            val = '$'            val = val + str(self.value)        else:            val = '-$'            val = val + str(self.value)[1:]        return val    def __nonzero__(self):        if self.value == 0:            return False        else:            return Trueif __name__ == '__main__':    cash = MoneyFmt(-123.45)

18.
网上答案是生成一个list类型的子类
这里我是生成了13-4自己写的类的子类来做的
这段代码只写了逻辑,没测试运行了,写的不是很完善。
生成了个userdb的子类,子类中有个方法可以修改用户密码。
用户密码进行了保存,数据格式{name:[[passwd,time],[…]]}需要判断时去遍历读取。
判断相似只判断了用户是否只更改了密码的大小写,想到的比较严谨的是使用余弦向量对文本进行判断。

# -*- coding: utf-8 -*-import timeclass userdb(object):    db = {}    psdb = {}    index = False    #初始化时加载文件信息,这个地方严格来说也要加载一个passwd的数据进来    #感觉自己的算法写的不是很好,就不实现这个了    def __init__(self):        f = open('ar.txt','r')        lines = f.readlines()        f.close()        for line in lines:            #split返回的是list            st1 = line.split(':')            st2 = st1[1].split(',')            name = st1[0]            paswd = int(st2[0])            time = st2[1].strip()            li = []            li.append(paswd)            li.append(time)            self.db[name] = li        # for i in self.db:        #     print i,self.db[i]    #登录    def login(self,name,paswd):        if self.db[name][0] == paswd:            #判断密码是否过期            li = self.psdb[name]            for i in li:                if i[0] == paswd :                    if time.localtime() - i[1]>12*30*24*60*60:                        print 'passwd out of time'                        break            else:                print 'your last time login:',self.db[name][1]                self.db[name][1] = time.strftime("%Y %m %d %H %M", time.localtime())                self.index = True        else:            print 'login fail'    #添加    def adduser(self,newname,newpaswd):        if self.index == True:            ti = time.strftime("%Y %m %d %H %M", time.localtime())            li = []            li.append(newpaswd)            li.append(ti)            self.db[newname] = li            #这个密码的初始时间            self.psdb[newname] = [[newpaswd,time.localtime()]]        else:            print 'you have not login in'    def __del__(self):        f = open('ar.txt','w')        for keys in self.db:            st = keys+':'+str(self.db[keys][0])+','+self.db[keys][1]            # print st            f.write(st)            f.write('\n')        f.close()class changePd(userdb):    def __init__(self,uname):        userdb.__init__(self)        self.uname = uname    def pdchange(self,newpd):        #相似这里就判断一下是否只改了大小写,认真写的话可以用相似度来判断一下,例如余弦向量什么的        li = self.psdb[self.uname]        #只要没有break就会执行else里面的内容        for i in li:            #当两个密码相似且时间间隔不到一年            if i[0].upper() == newpd.upper() and time.localtime() - i[1] <  12*30*24*60*60:                print 'similar passwd in one year'                break        else:            self.db[self.uname][0] = newpd            self.savefile()    def savefile(self):        f = open('ar.txt', 'w')        for keys in self.db:            st = keys+':'+str(self.db[keys][0])+','+self.db[keys][1]            # print st            f.write(st)            f.write('\n')        f.close()if __name__ =='__main__':    user = changePd('Anna')    user.pdchange('2132')    olduser = userdb()

19.
会陷入无限循环里面,因为重写了.keys方法, self.keys会首先调用子类的.keys方法,而子类的.keys方法中又调用了自己,形成了循环。这个地方必须申明调用父类的.keys方法才能取到键的值

python2.7版本里,super方法是只能用于新类的,在继承标准类时使用会出错。使用dict.keys(),即直接使用名字调用也会出错。
暂时没有找到子类同名函数中调用父类为标准类的方法,可能是版本不够的问题。

# -*- coding: utf-8 -*-class mydic(dict):    def skeys(self):        return sorted(self.keys())if __name__ =='__main__':    mydic = mydic((('zheng',23),('hui',32),('xin',56)))    print 'By itertor:'.ljust(12),[key for key in mydic]    print mydic.skeys()

20.
radd方法不用在这里实现,它是一个自定义的类操作符,作用是在a+b时(a,b都是实例),当a中没有定义add方法时,就在b中找radd操作符
add定义该类实例的加法(a+b中的a)
iadd定义该实例用于自加语法时的操作方法 a += b

# -*- coding: utf-8 -*-class Time60(object):    def __init__(self,*rest):        #输入的是这几种特殊的        if len(rest) == 1:            #注意这里rest已经是一个tuple类型            if type(rest[0]) == tuple:                self.hr = rest[0][0]                self.min = rest[0][1]            elif type(rest[0]) == dict:                self.hr = rest[0]['hr']                self.min = rest[0]['min']            elif type(rest[0]) == str:                index = rest[0].index(':')                self.hr = int(rest[0][:index])                self.min = int(rest[0][index+1:])        #无输入        elif len(rest) == 0:            self.hr = 0            self.min = 0        #正常输入        else:            self.hr = rest[0]            self.min = rest[1]    def __str__(self):        #2位,不足时以0占位        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 + self.min        if min >=60:            min = min - 60            hr = hr + 1        return self.__class__(hr,min)    def __iadd__(self, other):        self.hr += other.hr        self.min += other.min        if self.min>=60:            self.min = self.min -60            self.hr =self.hr+1        return selfif __name__ =='__main__':    # ti = Time60(12,5)    ti1 = Time60((10,30))    ti2 = Time60({'hr':10,'min':30})    ti3 = Time60('10:5')    # print ti    print ti1    print ti2    print ti3    print ti1+ti2    ti1 += ti2    print ti1

21.
装饰器的语法:

@decodef foo():passfoo = deco(foo)x = property(x)

x = property(**x()) 不是很能理解,按装饰器翻译过来应该是上面那句。