《Python核心编程》第11章 习题

11-2 函数。结合你对练习5-2的解,以便你创建一个带一对相同数字并同时返回它们之和以及产物的结合函数。

fun=lambda x,y:x+y
print fun(1,3)

11-3 函数。

在这个练习中,我们将实现max()和min()内建函数。

(a) 写分别带两个元素返回一个较大和较小元素,简单的max2()核min2()函数。他们应该可以用任意的python 对象运作。举例来说,max2(4,8)和min2(4,8)会各自每次返回8 和4。

(b) 创建使用了在a 部分中的解来重构max()和min()的新函数my_max()和my_min().这些函数分别返回非空队列中一个最大和最小值。它们也能带一个参数集合作为输入。用数字和字符串来测试你的解。

min2=lambda x,y:x if x<y else y
max2=lambda y,x:y if x<y else x
print min2(4,8)
print max2(8,4)

def my_max(*l):
    retval=l[0]
    for i in l:
        retval=max2(retval,i)
    return retval

def my_min(*l):
    retval=l[0]
    for i in l:
        retval=min2(retval,i)
    return retval

print my_max(1,9,4)
print my_max('av','bd','fd')
print my_min(1,9,4)
print my_min('av','bd','fd')

11–4. 返回值。

给你在5-13 的解创建一个补充函数。创建一个带以分为单位的总时间以及返回一个以小时和分为单位的等价的总时间。

print "input total time as minutes:"
min=int(raw_input('please input a number: '))
def fmttime(minutes):
    HH=minutes/60
    MM=minutes%60
    print '%d total minutes is %d hour %d min' %(minutes,HH,MM)
fmttime(min)

11–5 默认参数。更新你在练习5-7中创建的销售税脚本以便让销售税率不再是函数输入的必要之物。

def tax(rate=0.2):
    price=float(raw_input('please input a earn price: '))
    print 'your tax is %10.2f' %round(price*rate,2)

tax()

11–6. 变长参数。

下一个称为printf()的函数。有一个值参数,格式字符串。剩下的就是根据格式化字符串上的值,要显示在标准输出上的可变参数,格式化字符串中的值允许特别的字符串格式操作指示符,如%d, %f, etc。提示:解是很琐碎的----无需实现字符串操作符功能性,但你需要显示用字符串格式化操作(%)

def printf(fmt,*var):
    print fmt % var

printf('%d-%s-%s',2016,'01','06')

11–7. 用map() 进行函数式编程。

给定一对同一大小的列表, 如[1 , 2 , 3] 和['abc','def','ghi',....],将两个标归并为一个由每个列表元素组成的元组的单一的表,以使我们的结果看起来像这样:{[(1, 'abc'), (2, 'def'), (3, 'ghi'), ...}.(虽然这问题在本质上和第六章的一个问题相似,那时两个解没有直接的联系)然后创建用zip 内建函数创建另一个解。

def connect(list1,list2):
    if len(list1) != len(list2):
        print 'length of list must be equal'
    else:
        print map(None,list1,list2)
        print zip(list1,list2)

connect([1,2,3],['abc','def','ghi'])

11–8. 用filer()进行函数式编程.

使用练习5-4 你给出的代码来决定闰年。更新你的代码一边他成为一个函数如果你还没有那么做的话。然后写一段代码来给出一个年份的列表并返回一个只有闰年的列表。然后将它转化为用列表解析。

from random import randint

def leapyear(year):
    if year<1900 or year>2016:
         print 'year error'
    elif (year%4==0 and year%100!=0) or (year%400==0):
         return year
years=[]
for i in range(10):
    years.append(randint(1900,2016))
print years
print filter(leapyear,years)
#列表解析
print [n for n in [randint(1900,2016) for i in range(10)] if ((n%4==0 and n%100!=0) or (n%4==0 and n%100==0))]

11–9. 用reduce()进行函数式编程。

复习11.7.2 部分,阐述如何用reduce()数字集合的累加的代码。修改它,创建一个叫average()的函数来计算每个数字集合的简单的平均值。

def average(num):
    numlist=range(num)
    print 'the average is: ',reduce((lambda x,y:x+y),numlist)/len(numlist)
average(5)

11–11.用map()进行函数式编程。

写一个使用文件名以及通过除去每行中所有排头和最尾的空白来“清洁“文件。在原始文件中读取然后写入一个新的文件,创建一个新的或者覆盖掉已存在的。给你的用户一个选择来决定执行哪一个。将你的解转换成使用列表解析。

import os
def cleanfile(filename):
    print 'c: create a new clean file'
    print 'o: overwrite the original file'
    op=raw_input('pls input a choice:')
    if op.lower()=='c':
        newfilename=raw_input('pls input a new file name:')
        ofile=open(filename,'r')
        dfile=open(newfilename,'w')
        oflines=map((lambda line:line.strip()),ofile)
        #oflines=[line.strip() for line in ofile]
        for line in oflines:
            dfile.write(line)
            dfile.write(os.linesep)
        ofile.close()
        dfile.close()
    elif op.lower()=='o':
        ofile=open(filename,'r')
        oflines=map((lambda line:line.strip()),ofile)
        #oflines=[line.strip() for line in ofile]
        ofile.close()
        dfile=open(filename,'w')
        for line in oflines:
            dfile.write(line)
            dfile.write(os.linesep)
        dfile.close()
    else:
        print 'input error'

cleanfile('test.txt')

11–12. 传递函数。

给在这章中描述的testit()函数写一个姊妹函数。timeit()会带一个函数对象(和参数一起)以及计算出用了多少时间来执行这个函数,而不是测试执行时的错误。返回下面的状态:函数返回值,消耗的时间。你可以用time.clock()或者time.time(),无论哪一个给你提供了较高的精度。(一般的共识是在POSIX 上用time.time(),在win32 系统上用time.clock())注意:timeit()函数与timeit 模块不相关(在python2.3 中引入)

import time
def timeit(func,*nkwargs,**kwargs):
    try:
        start=time.clock()
        retval=func(*nkwargs,**kwargs)
        end=time.clock()
        result=(True,retval,end-start)
    except Exception,diag:
        result=(False,str(diag))
    return result

def test():
    funcs=(int,long,float)
    vals=(1234,12.34,'1234','12.34')
    for eachFunc in funcs:
        print '-'*80
        for eachVal in vals:
            retval=timeit(eachFunc,eachVal)
            if retval[0]:
                print '%s(%s)='%(eachFunc.__name__,eachVal),retval[1],
                print 'this func cost %s secs' % retval[2]
            else:
                print '%s(%s)=FAILED: ' %(eachFunc.__name__,eachVal),retval[1]

test()

11–13.使用reduce()进行函数式编程以及递归。

在第8 张中,我们看到N 的阶乘或者N!作为从1 到N 所有数字的乘积。
(a) 用一分钟写一个带x,y 并返回他们乘积的名为mult(x,y)的简单小巧的函数。
(b)用你在a 中创建mult()函数以及reduce 来计算阶乘。
(c)彻底抛弃掉mult()的使用,用lamda 表达式替代。
(d)在这章中,我们描绘了一个递归解决方案来找到N!用你在上面问题中完成的timeit()函数,并给三个版本阶乘函数计时(迭代的,reduce()以及递归)

import time
def timeit(func,*nkwargs,**kwargs):
    try:
        start=time.clock()
        retval=func(*nkwargs,**kwargs)
        end=time.clock()
        result=(True,retval,end-start)
    except Exception,diag:
        result=(False,str(diag))
    return result

def iteration(n):
    sum=1
    if n==0 or n==1:
        return 1
    else:
        for i in range(1,n+1):
            sum*=i
    return sum
def mult(x,y):
    return x*y
def myreduce(n):
    return reduce(mult,range(1,n+1))
    #return reduce(lambda x,y:x*y,range(1,n+1))
def factorial(n):
    if n==0 or n==1:
        return 1
    else:
        return n*factorial(n-1)

def test():
    eachVal=5
    funcs=(iteration,myreduce,factorial)
    for eachFunc in funcs:
        print '-'*60
        retval=timeit(eachFunc,eachVal)
        if retval[0]:
            print '%s(%s)='%(eachFunc.__name__,eachVal),retval[1],
            print 'this func cost %s secs' % retval[2]
        else:
            print '%s(%s)=FAILED: ' %(eachFunc.__name__,eachVal),retval[1]

test()

11–14. 递归。

我们也来看下在第八章中的Fibonacci 数字。重写你先前计算Fibonacci 数字的解(练习8-9)以便你可以使用递归。

def f(n):
    flist=[0,1,1]
    if 1==n or 2==n:
        return 1
    else:
        for i in range (2,n):
            flist.append(f(i)+flist[i-1])
    return flist[n]
print f(6)

11–15.递归。

从写练习6-5 的解,用递归向后打印一个字符串。用递归向前以及向后打印一个字符串。

def backward(s,i=0):
    if i < len(s):
        print s[0:i+1],  
        backward(s,i+1)
        
def forward(s,j=0):
    if j > -len(s):
        print s[j-1:],  
        forward(s,j-1) 
      
if __name__=='__main__':
    backward('abcdefg')
    print
    forward('abcdefg')

11-16 更新easyMath.py。这个脚本,如例子11.1描绘的那样,以入门程序来帮助年轻人强化他们的数学技能。通过加入乘法作为可支持的操作来进一步提升这个程序。额外的加分:也加入除法,这比较难做些因为你要找到有效的整型除数。幸运地是,已经有代码来确定分子比分母大,所以不需要支持分数。(没看太懂题目,瞎做的)

from operator import add,sub,mul,div
from random import randint,choice

ops = {'+':add, '-':sub, '*':mul, '/':div}
MAXTRIES = 2
5
def doprob():
    op = choice('+-*/')
    nums = [randint(1,10) for i in  range(2)]
    if op != '/':
        ans = ops[op](*nums)
        pr = '%d %s %d=' %(nums[0],op,nums[1])
    else:
        if nums[0]<nums[1]:
            nums.reverse()
        ans = ops[op](*nums)
        pr = '%d %s %d=' %(nums[0],op,nums[1])
    oops = 0
    while True:
        try:
            if int(raw_input(pr)) == ans:
                print 'correct'
                break
            if oops == MAXTRIES:
                print 'answer\n%s%d' %(pr,ans)
            else:
                print 'incorrect...try again'
                oops += 1
        except (KeyboardInterrupt,EOFError,ValueError):
            print 'invalid input...try again'

def main():
    while True:
        doprob()
        try:
            opt = raw_input('Again?[y]').lower()
            if opt and opt[0] == 'n':
                break
        except (KeyboardInterrupt,EOFError):
            break

if __name__=='__main__':
    main()

11-18 同步化函数调用。复习下第6章中当引入浅拷贝和深拷贝时,提到的丈夫和妻子情形。他们共用了一个普通账户,同时对他们银行账户访问会发生不利影响。创建一个程序,让调用改变账户收支的函数必须同步。换句话说,在任意给定时刻只能有一个进程或者线程来执行函数。一开始你试着用文件,但真正的解决办法是用装饰器和threading或者mutex模块中的同步指令。看看18章获得更多灵感。(没看懂题目,瞎做的)

person = ['name',['savings',100.00]]
hubby = person[:]
wifey = list(person)
hubby[0] = 'joe'
wifey[0] = 'jane'

def count(who):
    def cost(f,*args,**kargs):
        if len(args) != 2:
            print 'paras num error'
        elif args[0] == 'joe':
            hubby[1][1] -= args[1]
            print hubby,wifey,person
        elif args[0] == 'jane':
            wifey[1][1] -= args[1]
            print hubby,wifey,person
        else:
            print 'paras error'

    def hubby_cost(f):
        def wrapper(*args,**kargs):
            cost(f,*args,**kargs)
            return f(*args,**kargs)
        return wrapper

    def wife_cost(f):
        def wrapper(*args,**kargs):
            cost(f,*args,**kargs)
            return f(*args,**kargs)
        return wrapper

    try:
        return {'joe':hubby_cost,'jane':wife_cost}[who]
    except KeyError,e:
        raise ValueError(e),'must be "joe" or "jane"'

@count('joe')
def changehubby(name,money):
    print 'change count of %s, minus %f' % (name,money)

@count('jane')
def changewifey(name,money):
    print 'change count of %s, minus %f' % (name,money)

changehubby('joe',10.0)
changewifey('jane',20.0)


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值