闲来无事,碰到很多python的疑难杂症,觉得应该该这些问题整理起来,以来是对自己知识能力的检测,而来方便其他朋友,所以这篇文章会不断地被更新。总的来说,这些问题其实一点都不难,能解释清楚的东西,都不能算作是是难吧。
第一题,行列式转换
1 | #已知有一个二维列表(每一行的元素个数相同),写出函数对其行列转换并输出,比如: |
常规解法 按照常规解法,这道题需要编写两层循环,分别添加提取数组中的内容放入新数组:
解题思路一:
已经知道数组A是m*n的二维数组,那么输出必然是n*m,所以首先用生成器表达式生成了这样的数据结构(数组B),然后要做的事情就是让B[row,col] = A[col, row]
1 | def transpose(list_a): |
解题思路二:
和思路一大同小异,只不过是再循环中创建一个数组,这个数组用于存储B的每一行,然后把这个数组依次加入B。
1
2
3
4
5
6
7
8 def transpose2(list_a):
result = []
for x in range(len(list_a[0])):
tmp = []
for y in range(len(list_a)):
tmp.append(list_a[y][x])
result.append(tmp)
print result
充分利用python语言特性的解法:
解题思路三:
求解这道题的关键在于对zip函数函数的理解,zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。但是为了保持数据的一致性,我们最好还是把元组转成list。
1 | def tranpose2(list_a): |
第二题:写一个支持参数的装饰器
这个题比较简单了,直接参考python cook book元编程那一章,在这里就编写一个测量函数执行时间的装饰器函数吧。
1 | import time |
在上面的 wrapper() 函数中, 装饰器内部定义了一个使用 *args 和 **kwargs 来接受任意参数的函数。 在这个函数里面调用了原始函数并将其结果返回,不过你还可以添加其他额外的代码(比如计时)。 然后这个新的函数包装器被作为结果返回来代替原始函数。
需要强调的是装饰器并不会修改原始函数的参数签名以及返回值。 使用
*args
和**kwargs
目的就是确保任何参数都能适用。 而返回结果值基本都是调用原始函数func(*args, **kwargs)
的返回结果,其中func
就是原始函数。
第三题:编码实现range函数
首先分析一波range
函数,range函数接受三个参数,默认情况下接收一个参数表示范围,默认从零开始,默认步长为1,同时支持下降,递减,下面是简单的实现,做了大量的判断,代码看上去并不怎么美观:
1 | def irange(*args): |
第四题:求解约瑟夫环问题
有n个人围成一圈,从1开始按顺序编号,从第一个人开始从1到k(假设k=3)报数,报到k的人退出圈子,然后圈子缩小,从下一个人继续游戏,问最后留下的是原来的第几号。
解题思路:因为是循环报数,所以假设每一次报数都从数组的第一个元素开始,要保证这样,那就必须把报过数的人移动到数组的尾部,顺带删除数字的第k个元素,直到数组的长度变为1:。
1 | def find_last1(lst, k): |
还有一种方法是,直接使用python里的itertools.cycle:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16from itertools import cycle
def find_last2(lst, k):
t_lst = lst[:]
while len(t_lst)>1:
#创建cycle对象
c = cycle(t_lst)
#从1到k报数
for i in range(k):
t = next(c)
#一个人出局,圈子缩小
index = t_lst.index(t)
t_lst = t_lst[index+1:] + t_lst[:index]
#游戏结束
return t_lst[0]