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

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

#股票应有一个市场价格,每日变动,这个地方我设成定值3.0
class 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 os

class 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 00
Anna:2727,2017 09 13 10 00
Bnna:23214,21214
<open file 'ar.txt', mode 'r' at 0x00F9DF40>
Cnna:2828,2017 09 13 10 00
Anna:2727,2017 09 13 10 00
Bnna: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 division

class 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 True

if __name__ == '__main__':
    cash = MoneyFmt(-123.45)

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

# -*- coding: utf-8 -*-
import time

class 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 self


if __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.
装饰器的语法:

@deco
def foo():pass

foo = deco(foo)
x = property(x)

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值