题目013:写一个函数统计传入的列表中每个数字出现的次数并返回对应的字典。
点评:送人头的题目,不解释。
def count_letters(items):result = {}for item in items:if isinstance(item, (int, float)):result[item] = result.get(item, 0) + 1return result
也可以直接使用Python标准库中collections
模块的Counter
类来解决这个问题,Counter
是dict
的子类,它会将传入的序列中的每个元素作为键,元素出现的次数作为值来构造字典。
from collections import Counterdef count_letters(items):counter = Counter(items)return {key: value for key, value in counter.items() \if isinstance(key, (int, float))}
题目014:使用Python代码实现遍历一个文件夹的操作。
点评:基本也是送人头的题目,只要用过
os
模块就应该知道怎么做。
Python标准库os
模块的walk
函数提供了遍历一个文件夹的功能,它返回一个生成器。
import osg = os.walk('/Users/Hao/Downloads/')
for path, dir_list, file_list in g:for dir_name in dir_list:print(os.path.join(path, dir_name))for file_name in file_list:print(os.path.join(path, file_name))
说明:
os.path
模块提供了很多进行路径操作的工具函数,在项目开发中也是经常会用到的。如果题目明确要求不能使用os.walk
函数,那么可以使用os.listdir
函数来获取指定目录下的文件和文件夹,然后再通过循环遍历用os.isdir
函数判断哪些是文件夹,对于文件夹可以通过递归调用进行遍历,这样也可以实现遍历一个文件夹的操作。
题目015:现有2元、3元、5元共三种面额的货币,如果需要找零99元,一共有多少种找零的方式?
点评:还有一个非常类似的题目:“一个小朋友走楼梯,一次可以走1个台阶、2个台阶或3个台阶,问走完10个台阶一共有多少种走法?”,这两个题目的思路是一样,如果用递归函数来写的话非常简单。
from functools import lru_cache@lru_cache()
def change_money(total):if total == 0:return 1if total < 0:return 0return change_money(total - 2) + change_money(total - 3) + \change_money(total - 5)
说明:在上面的代码中,我们用
lru_cache
装饰器装饰了递归函数change_money
,如果不做这个优化,上面代码的渐近时间复杂度将会是 O ( 3 N ) O(3^N) O(3N),而如果参数total
的值是99
,这个运算量是非常巨大的。lru_cache
装饰器会缓存函数的执行结果,这样就可以减少重复运算所造成的开销,这是空间换时间的策略,也是动态规划的编程思想。
题目016:写一个函数,给定矩阵的阶数n
,输出一个螺旋式数字矩阵。
例如:n = 2,返回:
1 2 4 3
例如:n = 3,返回:
1 2 3 8 9 4 7 6 5
这个题目本身并不复杂,下面的代码仅供参考。
def show_spiral_matrix(n):matrix = [[0] * n for _ in range(n)]row, col = 0, 0num, direction = 1, 0while num <= n ** 2:if matrix[row][col] == 0:matrix[row][col] = numnum += 1if direction == 0:if col < n - 1 and matrix[row][col + 1] == 0:col += 1else:direction += 1elif direction == 1:if row < n - 1 and matrix[row + 1][col] == 0:row += 1else:direction += 1elif direction == 2:if col > 0 and matrix[row][col - 1] == 0:col -= 1else:direction += 1else:if row > 0 and matrix[row - 1][col] == 0:row -= 1else:direction += 1direction %= 4for x in matrix:for y in x:print(y, end='\t')print()
题目017:阅读下面的代码,写出程序的运行结果。
items = [1, 2, 3, 4]
print([i for i in items if i > 2])
print([i for i in items if i % 2])
print([(x, y) for x, y in zip('abcd', (1, 2, 3, 4, 5))])
print({x: f'item{x ** 2}' for x in (2, 4, 6)})
print(len({x for x in 'hello world' if x not in 'abcdefg'}))
点评:生成式(推导式)属于Python的特色语法之一,几乎是面试必考内容。Python中通过生成式字面量语法,可以创建出列表、集合、字典。
[3, 4]
[1, 3]
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
{2: 'item4', 4: 'item16', 6: 'item36'}
6
题目018:说出下面代码的运行结果。
class Parent:x = 1class Child1(Parent):passclass Child2(Parent):passprint(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
点评:运行上面的代码首先输出
1 1 1
,这一点大家应该没有什么疑问。接下来,通过Child1.x = 2
给类Child1
重新绑定了属性x
并赋值为2
,所以Child1.x
会输出2
,而Parent
和Child2
并不受影响。执行Parent.x = 3
会重新给Parent
类的x
属性赋值为3
,由于Child2
的x
属性继承自Parent
,所以Child2.x
的值也是3
;而之前我们为Child1
重新绑定了x
属性,那么它的x
属性值不会受到Parent.x = 3
的影响,还是之前的值2
。
1 1 1
1 2 1
3 2 3