这篇博客记录廖雪峰python教程的习题(一)

函数

函数的参数

  1. “以下函数允许计算两个数的乘积,请稍加改造,变成可接收一个或多个数并计算乘积:
    def product(x,y):
    return x*y

由于是可以接收一个或多个参数,所以想到定义函数时要用可变参数

def product(*numbers):  #这个地方*numbers就是可变参数,函数内部numbers其实是作为一个tuple
    sum=1
    for number in numbers:
        sum=sum*number
    return sum

def main():
    sum=product(1,2,34)
    print("the product of the numbers is {}".format(sum))

main()

递归函数

这里强调一点:使用递归函数的时候,一定要有终止的条件,不然程序就会一直运行下去!!!
2. ”汉诺塔的移动可以用递归函数非常简单地实现。
请编写move(n, a, b, c)函数,它接收参数n,表示3个柱子A、B、C中第1个柱子A的盘子数量,然后打印出把所有盘子从A借助B移动到C的方法,例如 move(3, ‘A’, ‘B’, ‘C’)
期待输出:
A –> C
A –> B
C –> B
A –> C
B –> A
B –> C
A –> C

汉诺塔的原理很简单:
当n=1时 ,直接:A—>C,只需一步。

当n=2时,我们可以先把上面的小盘子从A—>B ,然后把下面的大盘子从A—>C, 最后再把小盘子从B–>C, 一共需要三步。

当n=3时,我们可以先把上面的两个盘子按照n=2的做法先移动到B,上面已经分析出来 需要三步,(其实也是把n个盘子从一个地方移到另一个地方的一种实现,只不过这里n=2,C变为B了而已) ,然后把最下面的大盘子从A–>C,最后再把上面的两个盘子从B–>C 也是需要三步,总共需要七步。
·······

所以使用递归函数的代码为:

step=0
def move(n,a,b,c):
    global step
    if n==1:  #这个地方就是递归函数调用终止的条件
        print(a,'-->',c)
        step=step+1
    else:
        move(n-1,a,c,b)  #把上面n-1个从a-->b
        move(1,a,b,c)    #把最下面一个从a-->c
        move(n-1,b,a,c)  #把上面n-1个从b-->c

def main():
    n=eval(input("please input the numbers of the plates:"))
    move(n,'A','B','C')  #这里的A B C 表示圆柱
    print("the total steps to move the plates from a to c is {}".format(step))

main()

注: 刚开始使用step变量进行计数时发现即使把step变量定义在外边 还是会报错:

UnboundLocalError: local variable ‘step’ referenced before assignment
解决方法参考了这篇博客

高级特性

“构造一个1, 3, 5, 7, …, 99的列表”

def add_list(n):
    L=[]
    for i in range(1,n,2):
        L.append(i)
    return L

def main():
    n=eval(input("please input the numbers:"))
    l=add_list(n)
    print(l)

main()

切片

利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法:

#去除一个字符串首尾空格
def main():
    s=input("please input a string :")
    s0=trim(s)
    print("the string processed is"+s0)

def trimbegin(s):
    if s[0]!=' ':
        return s
    else:
        trimbegin(s[1:])
    print(s)

def trimend(s):
    if s[-1]!=' ':
        return s
    else:
        trimend(s[:-1])

def trim(s):
    s1=trimbegin(s)
    s2=trimend(s1)
    return s2

main()

上面的代码运行不对,,,,明天再看

嗯,犯了三个错误:
首先,判断某一个字符是不是空格时用 ’ ’ ,而不是 ”;
其次,在输入一个英文的字符串时不需要加引号!引号也是一个字符,并且是非空的,interesting
最后, 也是我昨天一直搞不明白的就是 递归调用时一定要有返回值return!否则它只会计算出最后那个被调用的函数的值,而不会返回给前面依次调用它的函数,切记!

好了,下面是正确的代码(另附了计算n的阶乘的例子,就是为了强调递归调用需要有返回值,否则最终计算的结果只会返回一个None!)

#去除一个字符串首尾空格

def main():
    s=input("please input a string :")
    s0=trim(s)
    print("the string processed is"+s0)

def trimbegin(s):
    if s[0]!=' ':
        return s
    else:
        return trimbegin(s[1:])    #此处不加return会有错误,NoneType 
    print(s)

def trimend(s):
    if s[-1]!=' ':
        return s
    else:
        return trimend(s[:-1])

def trim(s):
    s1=trimbegin(s)
    s2=trimend(s1)
    return s2

main()

'''
#递归调用时一定要有返回值,否则他只会计算出最后被调用的那个函数的值,而不会依次返回给前面调用它的函数!!!
#比如你在计算n!时用到递归,应该这样来写:
def factorial_n(n):
    if n==1:
        return 1
    else:
        return n*factorial_n(n-1)

def main():
    n=eval(input("please input a number:"))
    result=factorial_n(n)
    print("the final result is {}".format(result))

main()
'''

嗯,大功告成。

迭代

请使用迭代查找一个list中最小和最大值,并返回一个tuple:

代码:

def find_max_min(L): #查找一个列表中最大值和最小值的函数
    min=max=L[0]
    for x in L:
        if maxfor y in L:
        if min>y:
            min=y
    return min,max

def input_L(*numbers):  #其实这个函数不写也行 ,主要是练习使用可变参数构造一个list
    L=[]
    for number in numbers:
        L.append(number)
    return L

def main():
    #L=input_L(1,2,3) 
    L=[1,2,3,4,5]
    r=find_max_min(L)
    print(r)

main()

列表生成式

如果list中既包含字符串,又包含整数,由于非字符串类型没有lower()方法,所以列表生成式会报错,使用内建的isinstance函数可以判断一个变量是不是字符串,请修改列表生成式,通过添加if语句保证列表生成式能正确地执行:

[s.lower() for s in ['SHJ','DJSJKDL','45',78,'DKLKFG'] if isinstance(s,str)]

需要注意的是列表生成式的第一项就是生成列表的每一项元素的“模板”,只能是一项。

生成器

斐波那契数列的构造,这里是我自己写的,并没有使用生成器的代码:
版本1

def fabonacci(num):
    n1=0
    n2=sum=1
    for i in range(num):
        print(sum,end=' ')   #让print()输出结果不自动换行,而是每两个结果之间加一个空格
        sum=n1+n2   #数列中下一个值就是前两个数的和
        n1=n2       #更新n1,其实就是原来的n2
        n2=sum      #更新n2,其实就是原来的sum值

def main():
    num=eval(input("please input a number:"))
    fabonacci(num)

main()

版本2

#其实可以不用三个变量 两个变量足够
def fabonacci(num):
    a,b=0,1
    for i in range(num):
        print(b,end=' ')
        a,b=b,a+b  #扎心了
def main():
    num=eval(input("please input a number:"))
    fabonacci(num)

main()

分析一下就是:(0) 1 1 2 3 5 8,,,,
1. 首先赋值 a b
2. 输出 b (也就是斐波那契数列的第一个数)
3. 计算 a+b
4. 第二次 a b
5. 重复2-4步

版本3
把上面的fabonacci()函数改成生成器,其实就是把里面的print()函数改为yield()函数即可,对于generator对象来说,只需要使用for循环即可取值,或者不断调用next(g)

#可以把上面写的fabonacci()函数改成一个生成器
def fabonacci(num):
    a,b=0,1
    for i in range(num):
        #print(b)
        yield(b)   #就是把上面的fabonacci()函数中的print()函数改为yield()函数即可
        a,b=b,a+b
    return "yeah!"

def main():
    num=eval(input("please input a number:"))
    g=fabonacci(num)     #这样g就变成一个生成器 generator
    for n in g:          #对generator来说使用for 循环即可取值
        print(n,end=' ') #为了让输出结果不自动换行  

main()

运行代码之后会出现指定num个数的数列,可是并没有给我们返回代码中的 return ‘yeah!’,这里可以使用StopIteration

#下面这个版本可以让上面的return语句也输出,这就需要使用StopIteration 

def fabonacci(num):
    a,b=0,1
    for i in range(num):
        yield(b)
        a,b=b,a+b
    return "yeah!"

def main():
    num=eval(input("please input a number:"))
    g=fabonacci(num)
    while True:
        try:
            n=next(g)
            print(n,end=' ')
        except StopIteration as e:
            print("\nthe content of the return is "+e.value)
            break

main()

关于杨辉三角,把每一行看做一个list,试写一个generator,不断输出下一行的list:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

我能说我是真的想了好久都没想出来吗,,,
原来真的存在智商碾压这种东西 smile.jpg

嗯,就是列表生成式和生成器没学好,,,,

直接附上代码,参考了这篇博客

#输出杨辉三角形,没有使用generator
def triangle(num):
    L=[1]
    for i in range(1,num+1):  #用来输出多行的
        print(L)     #首先输出第一行
        L=[L[j]+L[j+1] for j in range(len(L)-1)]  #使用列表生成式来生成下一行列表(借助于本行生成下一行)
        L.insert(0,1)  #因为杨辉三角形每行的第一个元素都是1
        L.append(1)    #末尾追加一个1

def main():
    num=eval(input("please input a number:"))
    triangle(num)

main()        

这里生成下一行的list列表时使用的是列表生成式,并没有使用generator ,当我把print(L) 改成yield时,发现没办法为首尾追加1
,有待修改

map_reduce函数

下面继续一个例子,使用map()函数和reduce()函数把字符串转成整数,然后进行相应的运算
代码如下:

#版本1
'''
#主要是利用map()函数把字符串转成int类型,然后使用reduce()函数对这些数字完成相应的功能
from functools import reduce

#这个函数的功能主要是把两个整数变为一个整数,分别由十位数和个位数
def add(x,y):
    return x*10+y   

#这个函数是把字符和对应的数字组成一个key_value,利用字典dictionary[key] 进行str和int的转化
def str_int(s):
    d={'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
    return d[s]

def main():
    result=reduce(add,map(str_int,'123456'))  #此处需要注意 ‘123456’是一个字符串序列,符合map作用的条件:第一个参数是函数,第二个参数是Iterable对象
    print("the final result is {}".format(result))

main()
'''

#版本2:
from functools import reduce

def finalfun(s):

    def add(x,y):
        return x*10+y

    def str_int(s):
        d={'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
        return d[s]
    #return reduce(add,map(str_int,s))
    return reduce(lambda x,y:10*x+y,map(str_int,s))

def main():
    result=finalfun('12344576')
    print("the final result is {}".format(result))

main()

“利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:[‘adam’, ‘LISA’, ‘barT’],输出:[‘Adam’, ‘Lisa’, ‘Bart’]:”
为什么我的代码很复杂,,而且我还想了好久,,,
所以吃什么可以拯救智商啊 smile.jpg

代码如下:

#第一下题:
#利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。

def normalize(s):
    for ch in s:
        s1=s.upper()   #把所有的字符都大写

    for ch in s[1:]:
        s2=s.lower()   #把所有的字符都小写

    s=s1[0]+s2[1:]     #然后只取上面的第一个字符(因为首字母要大写),去下面的剩下字符,,
    return s


def main():
    L=['sJKjf','hDJdjhf','HHkjdfk']
    s=list(map(normalize,L))
    print(s)

main()

“Python提供的sum()函数可以接受一个list并求和,请编写一个prod()函数,可以接受一个list并利用reduce()求积”

代码如下

#第二小题
# 请编写一个prod()函数,可以接受一个list并利用reduce()求积

from functools import reduce

def prod(L):  #使用reduce()函数对list中的数进行求和
    def product(x,y):   #首先定义两个数相乘的函数
        return x*y
    result=reduce(product,L) #使用reduce()函数对列表中的数求和
    return result

def main():
    L=[]
    n=eval(input("please input a number:"))  #n是你打算输入的list中的个数
    for i in range(n):      #通过输入的数构建list列表
        num=eval(input("please input a series of numbers:"))
        L.append(num)
    result=prod(L)
    print("the final result is {}".format(result))

main()

还想再说一遍我的智商真的不够用。这一个破题还纠结了这么久,难道不应该是拿起来就撸代码的操作吗?要疯
代码如下:

#第三小题
#利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数123.456:

from functools import reduce

def main():
    s='123.456'
    s=s.split('.')  #s=['123','456']
    s1=s[0]         #s1=['123']
    s2=s[1]         #s2=['456']
    #这就跟前面的操作一样了嘛,先定义str_int 使用map()函数把每一个字符串变为整数,再定义add_1()和add_2()函数 使用reduce()函数把离散的整数,变为一个完整的百位数和小树
    d1=reduce(add_1,map(str_int,s1))  #d1就是整数部分123
    #d2=reduce(add_2,map(str_int,s2))  #d2就是小数部分0.456
    d2=reduce(add_1,map(str_int,s2))
    d=d1+d2*0.001
    print("the data proceed is {}".format(d))


def str_int(s):
    d={'1':1,'2':2,'3':3,'4':4,'5':5,'6':6}
    return d[s]

def add_1(x,y):  #该函数是生成百位数
    return x*10+y

'''def add_2(x,y):  #该函数是生成小数
    return x+0.1*y ''' 

main()    

接下来一个例子是计算素数,采用的原理是埃氏筛法
思路很简单就是
1.首先去除1的全体自然数中2 是第一个,所以2就是一个素数;
2.然后从这个序列中用2 把所有2的倍数去掉,也就是只剩下奇数了,所以我们可以构建一个以3为开头的奇数序列,odd_all() 注意使用yield()函数把它变为Iterator
3.然后写一个not_division()函数把所有再odd_all()序列中第一个数的倍数过滤掉
4.odd_all()生成的奇数序列进行更新,再重复步骤3即可

代码如下:

#输出一个序列范围内的所有素数
#距离上一次感受到智商被碾压仅仅是两个小时前,心态已崩 

def odd_all():
    n=1
    while True:
        n=n+2
        yield n

def not_division(n):
    return lambda x:x%n>0

def prims():
    n=2
    it=odd_all()
    while True:
        yield n
        n=next(it)
        it=filter(not_division(n),it)

def main():
    for i in prims():
        if i<=30:
            print(i,end=' ')
        else:
            break

main()

“回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数”

思路很简单就不赘述了,嗯总算写出来了
代码如下:

#回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数

def main():
    L=[121,12332,12321,897878,9009]
    L1=list(filter(fun,L))    #使用filter用fun函数对L进行过滤,将过滤后的在组成一个list
    print(L1)   
    #L2=reverse(L)
    #print(L2)

def fun(num):
    L1=L2=[]

    for i in str(num):   #对于每一个输入的数字,首先将其转为字符串,然后for in 循环依次存入列表
        L1.append(i)     #L1列表中就对每一个数字顺序存放
    #print(L1)

    L2=reverse(L1)      #调用自定义的reverse函数,把刚才顺序存放的列表倒过来

    for i in range(len(L1)):   #这里主要就是对顺序存放的列表和反过来存放的列表看其元素是否相等 即是否是回数
        if L1[i]!=L2[i]:
            return 0
    return 1


def reverse(L):     #反转列表中的元素
    L1=[]
    for i in L:
        L1.append(L[-1])   #总是先存列表的最后一个元素
        L=L[:-1]           #然后把列表的最后一个元素去掉 是为了下次循环时存原来列表的倒数第二个,以此类推
    return L1

main()

废话

,到filter的习题先写到这,明天也要加油鸭!

你可能感兴趣的:(python_practice)