python标准库,内置函数面试题

8. 标准库,内置函数面试题

8.1 python中生成随机整数、随机小数、0--1之间小数方法

难度指数: ★
重要指数: ★★

随机数相关的模块是random模块, 三个方法分别提供随机整数,随机0到1之间的小数和任意两个数之间的小数

import random

print(random.randint(0, 10))        # 生成随机整数 [a, b] 左闭右闭
print(random.random())              # 生成[0, 1) 之间的小数
print(random.uniform(3.2, 6.7))     # 生成[a, b] 之间的小数

唯一的需要关注的是生成随机数的范围,中括号表示闭, 小括号表示开,[a, b)表示左闭右开,表示结果可以为a, 但一定不会为b,a <= 随机结果 < b

8.2 说说常用的标准库

难度指数: ★
重要指数: ★★
  1. os 提供了与操作系统相关的功能
  2. sys 提供了python环境和程序执行相关的信息
  3. math模块提供了很多与数学相关的函数
  4. random提供一系列方法可以让你获得随机数
  5. hashlib提供了常用的摘要算法如MD5,SHA1等等,摘要算法又称散列算法,哈希算法
  6. statistics 提供了一些计算数学统计量的函数
  7. re 处理正则
  8. datetime 处理日期时间

8.3 字典根据键从小到大排序

难度指数: ★
重要指数: ★★

题目要求

有字典dic,内容为

dic = {1:3, 2:2, 3:1}

根据键进行排序,其结果为 [(2, 7), (3, 1), (5, 3)], 根据value进行排序,其结果为[(3, 1), (5, 3), (2, 7)]

字典本身是无序的,python3与2不同,python3的字典在遍历时,可以根据写入key-value对的顺序进行遍历。题目的要求是获得一个列表,列表里的元素都是元组,元组的第一个元素是key, 第二个元素是value,对序列排序,就要用最强大的sorted函数

dic = {5:3, 2:7, 3:1}

sort_by_key = sorted(dic.items(), key=lambda x: x[0])
sort_by_value = sorted(dic.items(), key=lambda x: x[1])

print(sort_by_key)      # [(2, 7), (3, 1), (5, 3)]
print(sort_by_value)    # [(3, 1), (5, 3), (2, 7)]

8.4 正则表达式---提取汉字

难度指数: ★★
重要指数: ★★★

题目要求:

字符串a = "not 404 found 张三 99 深圳",每个词中间是空格,用正则过滤掉英文和数字,最终输出"张三 深圳"

正则表达式也是面试中经常被问到的问题,对于这个题目,有好几种方法,你都应当掌握

8.4.1 直接提取汉字

import re

s = "not 404 found 张三 99 深圳"
pattern = re.compile("[\u4e00-\u9fa5]+")
lst = pattern.findall(s)  # ['张三', '深圳']
print(" ".join(lst))

在unicode中汉字的编码是连续的,从\u4e00到\u9fa5, [\u4e00-\u9fa5] 表示汉字中的某一个,后面的加号表示1或n个, 这样就可以匹配到连续的汉字,findall以列表的形式返回匹配的汉字,最后使用空格连接。

8.4.2 使用sub方法过滤数字和字母

import re

s = "not 404 found 张三 99 深圳"
pattern = re.compile("[0-9a-zA-Z]")
string = pattern.sub("", s)
print(" ".join(string.split()))

[0-9a-zA-Z]匹配所有数字和字母,sub方法会将正则表达式匹配的部分替换成空字符串,得到string并不是最终想要的结果,因为原来的数字和字母部分都替换成了空字符串,留下了很多空格,使用split函数切分后得到['张三', '深圳'], 再用空格连接。

8.4.3 使用split 切分

import re

s = "not 404 found 张三 99 深圳"
pattern = re.compile("[\d+|(a-z)+\s+]")
lst = pattern.split(s)  # ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '张三', '', '', '', '深圳']
lst = [item for item in lst if item]    # ['张三', '深圳']
print(" ".join(lst))
  1. \d+, \d 代表数字,+ 表示1或n个, \d+表示1或n个数字
  2. (a-z)+, (a-z) 表示小写字母,(a-z)+表示1或n个小写字母
  3. \s+, \s 表示空白符,包括空格,\s+ 表示1或n个空白符

使用数字,字母,空格做分隔符切分字符串,会得到很多空字符串,对他们进行一次过滤,再用空格连接

8.4.4 找出英语单词和数字部分

import re

s = "not 404 found 张三 99 深圳"
pattern = re.compile("\d+|[a-zA-Z]+")
lst = pattern.findall(s)        # ['not', '404', 'found', '99']
result = s.split()              # ['not', '404', 'found', '张三', '99', '深圳']

result = list(set(result).difference(set(lst)))    # ["张三", "深圳"]
print(" ".join(result))

8.5 考察Counter

难度指数: ★
重要指数: ★★

题目要求:

利用collections库的Counter方法统计字符串每个字符出现的次数”kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h”

这是一个送分题目,不需要你编写任何算法,能正确使用Counter 就可以了

from collections import Counter

a = "kjalfj;ldsjafl;hdsllfdhg;lahfbl;hl;ahlf;h"
res = Counter(a)
print(res)    # Counter({'l': 9, ';': 6, 'h': 6, 'f': 5, 'a': 4, 'j': 3, 'd': 3, 's': 2, 'k': 1, 'g': 1, 'b': 1})

8.6 filter用法

难度指数: ★
重要指数: ★★

题目要求:

filter方法求出列表所有奇数并构造新列表,a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

filter用于过滤数据,但filter返回的是一个生成器,题目要求构造新列表,这一点审题要注意

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
lst = [item for item in filter(lambda x: x % 2 == 1, a)]
print(lst)

8.7 用python删除文件和用linux命令删除文件方法

难度指数: ★
重要指数: ★★

python的os.remove可以删除文件,但在删除前,应当使用os.path.exists()函数判断一下文件是否存在,不存在时调用remove函数删除会引发文件不存在的异常。

如果要删除文件夹,可以使用os.removedirs函数,但该函数只能删除空的文件夹,想要删除一个不空的文件夹,可以使用shutil.rmtree(path) 函数来进行删除。

linux系统里,使用rm 可以删除文件,如果想要删除文件夹,使用rm -rf 命令,这样即便文件夹非空,也可以删除。

8.8 正则表达式中(.*)和 (.*?)的区别是什么

难度指数: ★★★
重要指数: ★★★

(.*) 是贪婪匹配,会把满足正则的尽可能多的往后匹配

(.*?) 非贪婪匹配,会把满足正则的尽可能少匹配

举个例子进行说明

import re

pattern_1 = re.compile("{(.*)}")
pattern_2 = re.compile("{(.*?)}")

string = "{hello} {world}"
result_1 = pattern_1.findall(string)
result_2 = pattern_2.findall(string)

print(result_1)     # ['hello} {world']
print(result_2)     # ['hello', 'world']

使用贪婪匹配时,遇到第一个左大括号,会向后一直寻找最后一个右大括号,而使用非贪婪匹配,找到第一个右大括号就算匹配上。

8.9 考察join

难度指数: ★
重要指数: ★★

题目要求:

x="abc",y="def",z=["d","e","f"],分别求出x.join(y)和x.join(z)返回的结果

这是一道铁铁的送分题目,只要了解join方法的作用就能答得出来。唯一的一个小麻烦在于,你平时所见的都是用某个字符串去连接列表里的字符串,但变量y是一个字符串啊。

这就是理解的还不够深入,字符串的join方法,所能传入的数据并不只是列表,而是iterable, 可迭代对象,字符串也是可迭代对象,对字符串y进行迭代,得到的是单个字母,把这些字母用x连接起来就是最终结果,因此两个写法的最终结果是一致的,都是dabceabcf, x.join(y) 等价于下面的代码

s = ""
for item in y:
    s += item + x
print(s[:-len(x)])      # dabceabcf

8.10 举例说明zip()函数用法

难度指数: ★
重要指数: ★★

zip函数是一个非常拥有的函数,它可以将多个可迭代对象作为参数,将对象中对应的元素打包成元组,如果可迭代对象的长度不同,则根据长度最短的那个进行打包。

举例说明

lst1 = [1, 2, 3, 4, 5]
lst2 = ['一', '二', '三', '四', '五']

如果要将上面的两个列表整合成一个字典

{1: '一', 2: '二', 3: '三', 4: '四', 5: '五'}

采用普通方法的算法是这样的

lst1 = [1, 2, 3, 4, 5, 6]
lst2 = ['一', '二', '三', '四', '五']

info = {}
for index, item1 in enumerate(lst1):
    if index < len(lst2):
        info[item1] = lst2[index]

print(info)

for循环一次只能遍历其中一个列表,但使用zip就可以同时遍历这两个列表

lst1 = [1, 2, 3, 4, 5, 6]
lst2 = ['一', '二', '三', '四', '五']

info = {}
for item1, item2 in zip(lst1, lst2):
    info[item1] = item2

print(info)

代码是不是清爽了许多,你想更加清爽,可以使用字典推导式

lst1 = [1, 2, 3, 4, 5, 6]
lst2 = ['一', '二', '三', '四', '五']

info = {item1: item2 for item1, item2 in zip(lst1, lst2)}
print(info)

8.11 简述any()和all()函数

难度指数: ★
重要指数: ★★
  1. any() 函数用于判断给定的可迭代参数 iterable 是否有True,只要有一个等价于True,函数就返回True,否则返回False
  2. all() 函数用于判断给定的可迭代参数 iterable 是否全部为 True,只要有一个等价于False, 就返回False, 否则返回True

举例说明

print(any([False, 6 > 3, '', 8]))       # 结果是True, 因为6 > 3 结果为True,8 等价于True

print(all([8 > 4, True, '']))            # 结果是False, 因为 空字符串等价于False

8.12 sort和sorted的区别是什么

难度指数: ★
重要指数: ★★
  1. sort是列表的一个方法,只应用在列表上
  2. sorted是内置函数,可以应用于所有可迭代的对象上进行排序,功能比sort更加强大
  3. sort是就地排序,不会返回新的列表
  4. sorted 会返回一个新的排序后的列表

8.13 sorted用法

难度指数: ★★★
重要指数: ★★

题目要求:

使用sorted 进行排序对list排序foo =[-5,8,0,4,9,-4,-20,-2,8,2,-4],正数从小到大,负数从大到小, 最终结果为

[0, 2, 4, 8, 8, 9, -2, -4, -4, -5, -20]

这是一道比较考验功力的题目,只有真正理解sorted用法的人才能回答得出,我先放出答案,再解释原理

foo =[-5, 8, 0, 4, 9, -4, -20, -2, 8, 2, -4]
result = sorted(foo, key=lambda x: (x < 0, abs(x)))
print(result)

你或许在网上也看到了类似的答案,但是并没有人详细解释为什么这么做是有效果的。首先我们要弄清楚sorted排序的原理,它的key究竟是要起什么作用。如果列表里的数据都是int,那么几乎就用不到key,因为int与int之间能够进行大比较,但如果列表里的元素是那种无法确定比较大小方法的数据呢?比如下面的数据

lst = [(5, 2), (1, 6)]

请问,到底是(5, 2) 大,还是(1, 6) 大? 如果以元组第一个元素来比较那么(5, 2)大,如果以元组第二个元素来比较大小,则(1, 6)大,到底用哪个来比较大小呢,这个时候就可以用key来决定了

lst = [(5, 2), (1, 6)]

print(sorted(lst, key=lambda x: x[0]))      # 用元组第一个元素进行大小比较  [(1, 6), (5, 2)] 
print(sorted(lst, key=lambda x: x[1]))      # 用元组第二个元素进行大小比较  [(5, 2), (1, 6)]

如果不指定key呢,默认会使用元组第一个元素进行大小比较。关于key,我们还可以换一种方法来理解,如果以元组的第二个元组进行大小比较,就相当于说,2 代表(5, 2),6 代表(1, 6) 进行比较。

回头来看 lambda x: (x < 0, abs(x)) , 当x的 -5 时,lambda的返回值是元组(True, 5), 当x = 8 时,lambda的返回值是元组(False, 8), (True, 5) 代表-5 ,(False, 8)代表8 进行大小比较,两个元组进行大小比较,默认用元组的第一个元素进行比较,False等价于0, True等价于1, 比较的结果是8 小于 -5 ,注意,8是比-5大的,但是我们让(False, 8)代表8与代表-5 的 (True, 5) 进行比较,所以结果上,8 比 -5 小。

当元组第一个元素相同时,则使用元组的第二个元素继续比较,最终就得到了我们想要的结果

8.14 列表嵌套字典的排序

难度指数: ★★
重要指数: ★★

题目要求:

分别根据年龄和姓名排序 foo = [{"name":"zs","age":19},{"name":"ll","age":54}, {"name":"poly","age":22}]

经过8.13题目的洗礼,sorted函数的用法应当已经掌握了,我这里直接给出答案

foo = [{"name":"zs","age":19},{"name":"ll","age":54}, {"name":"poly","age":22}]

result = sorted(foo, key=lambda x: x['name'])       # 以姓名排序
print(result)   # [{'name': 'll', 'age': 54}, {'name': 'poly', 'age': 22}, {'name': 'zs', 'age': 19}]

result = sorted(foo, key=lambda x: x['age'])        # 以年龄排序
print(result)   # [{'name': 'zs', 'age': 19}, {'name': 'poly', 'age': 22}, {'name': 'll', 'age': 54}]

8.15 python字典和json字符串相互转化方法

难度指数: ★★ 
重要指数: ★★★★

字典与json字符串的转换要用json模块,是必须掌握的知识点,工作中,会大量的使用对象的序列化与反序列化操作

import json

data = {"name": 'python'}

# 字典转json字符串
json_str = json.dumps(data)
print(json_str)

# json字符串转字典
data = json.loads(json_str)
print(data)

字典转json字符串要用json.dumps函数,json字符串转字典用json.loads函数
这个问题,仅仅回答到这里是不够的,还要回答如何将字典保存到文件中,又如何从文件中加载数据转为字典

import json

data = {"name": 'python'}

with open('data', 'w')as f:
    json.dump(data, f)

with open('data', 'r')as f:
    data = json.load(f)
    print(data, type(data))

将对象序列化到文件中,使用json.dump()函数, 从文件读取数据反序列化使用jons.load()函数。

8.16 r、r+、rb、rb+文件打开模式区别

难度指数: ★★ 
重要指数: ★★★

这个题目考察的是对文件读写模式的理解

  1. r 是以只读模式打开文件
  2. r+ 以读写的方式打开文件,文件指针放在文件的开头
  3. rb 以二进制只读方式打开文件,文件指针放在文件的开头
  4. rb+ 以二进制读写方式打开文件,文件指针放在文件的开头

文件打开模式

  1. r 代表读
  2. w 代表写
  3. a 代表追加
  4. b 代表二进制
  5. + 表示读写

8.17 Python里面search()和match()的区别

难度指数: ★★ 
重要指数: ★★
  1. match()函数只检测字符串开头位置是否匹配,匹配成功才会返回结果,否则返回None
  2. search()函数会在整个字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象

举例说明

import re

string = "hello word"
print(re.match('hell', string))     # <_sre.SRE_Match object; span=(0, 4), match='hell'>
print(re.match('word', string))     # 虽然word存在,但不是在开头, 返回None

print(re.search('hell', string))    # <_sre.SRE_Match object; span=(0, 4), match='hell'>
print(re.search('word', string))    # <_sre.SRE_Match object; span=(6, 10), match='word'>

8.18 如何方便的查看一个对象所拥有的属性和方法

难度指数: ★
重要指数: ★★

python的变量是没有类型的,变量只是对象的引用,尽管现在有类型标注,但在调试程序的过程中,仍然不能方便的确定变量所引用对象的类型。你可以使用type函数来查看一个变量的类型,这有助于你理解程序,但如果使用了第三方库,第三方库返回的对象就是你不熟悉的对象,如果没有详细的文档,你甚至不知道这个对象有什么属性,有什么方法,这个时候就可以使用dir函数来查看

class T:
    def __init__(self, name):
        self.name = name

    def run(self):
        print('run')

t = T('小明')
print(dir(t))   # [.... 'name', 'run']

dir会返回对象t所拥有的属性和方法名称,其中有很多都是以双下滑线开头的,我们要关注那些不带双下划线的。

8.19 字符串格式化方法都有哪些

难度指数: ★★
重要指数: ★★★★

字符串格式化,是使用频率非常高的技术,主要有三种方法

  1. 使用 %
  2. 使用 format函数
  3. 使用f-string

举例说明

name = "小明"
age = 14

str_format = "%s今年%d岁了"
print(str_format % (name, age))

str_format = "{name}今年{age}岁了"
print(str_format.format(name=name, age=age))

print(f"{name}今年{age}岁了")

三种方法里,使用% 是最初级的,也是不建议使用的,format方法相比于% 要高级一些,不过f-string才是当前格式化字符串的最佳选择

8.20 read,readline和readlines的区别

难度指数: ★★
重要指数: ★★
  1. read 读取整个文件内容,返回一个字符串
  2. readline 读取一行数据,返回一个字符串
  3. readlines 读取所有数据,以列表的形式返回

read 和 readlines 都是读取所有数据,如果文件非常大,不建议使用这两个方法来读取数据,readline会读取一行数据,因此不会占用内存,当文件很大时,应当使用readline,除了这三个方法以外,我更推荐对文件对象进行遍历

from collections import Iterable

with open('data', 'r')as f:
    print(isinstance(f, Iterable))      # True f是可迭代对象

    for line in f:
        print(line.strip())

打开的文件对象f是可迭代对象,直接对其使用for循环迭代更加方便

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案