《Python核心编程》第十一章练习解析

第一题:

参数。比较下面3个函数:

def countToFourl():
    for eachNum in range(5):
        print eachNum,
def countToFourl(n):
    for eachNum in range(n,5):
        print eachNum
def countToFour3(n=1):
    for eachNum in range(n,5):
        print eachNum,

给定如下的输入直到程序输出,你认为会发生什么?向下表11. 2填入输出。如果你认为给定的输入会发生错误的话填入“ERROR”或者如果没有输出的话填入“NONE”。

input countToForu1 countToForu2 countToForu3
2 0 1 2 3 4 2 3 4 2 3 4
4 0 1 2 3 4 4 4
5 0 1 2 3 4 NONE NONE
nothing 0 1 2 3 4 ERROR 1 2 3 4

第二题:

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

PS:如果题意没有理解错的话就是如下的代码

def count(num1,num2):
    return (num1*num2,num1+num2)

第三题:

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

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

def max2(x,y):
    if x < y:
        return y
    else:
        return x
        
def min2(x,y):
    if x < y:
        return x
    else:
        return y

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

def my_max(x):
    if x:
        return sorted(x,reverse=True)[0]
    
def my_min2(x):
    if x:
        return sorted(x)[0]

第四题:

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

def convert(minute):
    return (minute/60,minute%60)

第五题:

默认参数。更新你在练习5-7中创建的销售税脚本以便让销售税率不再是函数输入的必要之物。创建使用你地方税率的默认参数如果在调用的时候没有值传入。

def count(money,rate=0.1):
    return money*rate

第六题:

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

def printf(rule,*num):
    i = -1
    for j in num:
        i = rule.find("%",i+1)  #对%定位,分三种情况讨论并进行替换
        if rule[i+1]=="d" and type(j)==int:
            result = rule.replace("%d",str(j),1)
        elif rule[i+1]=="f" and type(j)==float:
            result = rule.replace("%f",str(j),1)
        elif rule[i+1]=="s" and type(j)==str:
            result = rule.replace("%s",j,1)
        else:
             print  "ERROR"  #当对应类型不正确时抛出异常
             exit(0)
        rule = result
    print result

第七题:

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

print map(None, [1,2,3],"abc")
print zip([1,2,3],"abc")

第八题:

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

years = [1900,2000,2100]
print filter(lambda year:(year%4==0 and year%100!=0) or (year%400==0),years)
print [year for year in years if (year%4==0 and year%100!=0) or (year%400==0)]

第九题:

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

def average(alist):
    return reduce((lambda x,y:x+y), alist)/float(len(alist))

第十题:

用filter()进行函数式编程。在unix文件系统中,在每个文件夹或者目录中都有两个特别的文件:‘.’表示现在的目录,‘..’表示父目录。给出上面的知识,看一下os. listdir()函数的文档并描述这段代码做了什么:

files = filter(lambda x: x and x[0] != '.', os.listdir(folder))

获取非当前目录和父目录的目录内容。

第十一题:

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

#-*- coding:utf-8 -*-

def clear(mystring):
    return str(mystring.strip())+"n"

if __name__ == "__main__":
    with open("1.txt","r") as f:
        lines = f.readlines()
        result = map(clear,lines)  #map()函数
        #result = [str(line.strip())+"n" for line in lines]   #列表解析
    f.close()
    choise = raw_input("Do you want to make a new file? n/y")
    if choise=="y":
        filename = raw_input("Input your file name:")
        newfile = open(filename,"w")
        newfile.writelines(result)
        newfile.close()
    else:
        with open("1.txt","w") as f:
            f.writelines(result)
        f.close()

第十二题:

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

#-*- coding:utf-8 -*-

import time

def timeit(func,*nkwargs,**kwargs):
    start = time.clock()
    try:
        retval = func(*nkwargs,**kwargs)
        result = (time.clock()-start,retval)
    except:
        result = (time.clock()-start,False)
    return result
    
def test():
    funcs = (int,long,float)
    vals = (1234,12.34,"1234","12.34")
    
    for eachFunc in funcs:
        print "_"*20
        for eachVal in vals:
            retval = timeit(eachFunc,eachVal)
            if retval[1]!=False:
                print "%s time is %s" % (eachFunc.__name__,retval[0])
            else:
                print "ERROR"
                
if __name__=="__main__":
    test()

第十三题:

使用reduce()进行函数式编程以及递归。在第8章中,我们看到N的阶乘或者N作为从1到N所有数字的乘积。

(a)用一分钟写一个带x, y并返回他们乘积的名为mult (x, y)的简单小巧的函数。

def mult(x,y):
    return x*y

(b)用你在a中创建mult()函数以及reduce来计算阶乘。

def mult(x,y):
    return x*y
print reduce(mult, range(1,5))

(c)彻底抛弃掉mult()的使用,用lamda表达式替代。

print reduce(lambda x,y:x*y, range(1,5))

(d)在这章中,我们描绘了一个递归解决方案来找到N!用你在上面问题中完成的timeit()函数,并给三个版本阶乘函数计时(迭代的、reduce()和递归)。

import time

def fun1(n):
    '''迭代'''
    total = 1
    for eachNum in range(1,n):
        total += total*eachNum
    return total

def fun2(n):
    '''reduce'''
    return reduce(lambda x,y:x*y, range(1,n))

def fun3(n):
    '''递归'''
    if n == 1 or n==0:
        return 1
    return n*fun3(n-1)

def timeit(func,*nkwargs,**kwargs):
    start = time.clock()
    try:
        retval = func(*nkwargs,**kwargs)
        result = (time.clock()-start,retval)
    except:
        result = (time.clock()-start,False)
    return result
    
def test(n):
    funcs = (fun1,fun2,fun3)
    
    for eachFunc in funcs:
        retval = timeit(eachFunc,n)
        if retval[1]!=False:
            print "%s time is %s" % (eachFunc.__name__,retval[0])
        else:
            print "ERROR"
                
if __name__=="__main__":
    test(5)

第十四题:

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

def count(n):
    if n==1 or n==2:
        return 1
    return count(n-1)+count(n-2)

第十五题:

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

#向后打印
def printLeft(strTemp):
    if strTemp:
        print strTemp[0],
        return printLeft(strTemp[1:])
#向前打印
def printRight(strTemp):
    if strTemp:
        print strTemp[-1],
        return printRight(strTemp[:-1])

第十六题:

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

这一个就不做了,看着书抄代码挺没意思的。

第十七题:

定义

(a)描述偏函数应用和currying之间的区别。

偏函数解决这样的问题:如果我们有函数是多个参数的,我们希望能固定其中某几个参数的值。

Currying解决的是一个完全不同的问题:如果我们有几个单参数函数,并且这是一种支持一等函数(first-class)的语言,如何去实现一个多参数函数?函数加里化是一种实现多参数函数的方法。

(b)偏函数应用和闭包之间有什么区别?

闭包:一个可以使用另外一个函数作用域中的变量的函数。

偏函数:偏应用函数就是缺少部分或全部参数的函数。

(c)最后,迭代器和生成器是怎么区别开的?

生成器 是 迭代器 的真子集

第十八题:

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

略。

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注