老男孩教育专注IT教育10余年,只培养IT技术精英

全国免费咨询电话(渠道合作):400-609-2893

【学习必看】Python面试宝典之Python基础

老男孩IT教育

常见问题

2021年8月23日 18:17

为了帮助大家更好的吸收和加强python知识,yuan老师特此完成一篇关于python最精华的面试题册,通过对这两年每一期毕业学生的实际面试题的收集和整理,代表着当前市场对于python的最实际的需求和前沿方向,希望能帮助到大家。

  为了帮助大家更好的吸收和加强python知识,老男孩教育yuan老师特此完成一篇关于python最精华的面试题册,通过对这两年每一期毕业学生的实际面试题的收集和整理,代表着当前市场对于python的最实际的需求和前沿方向,希望能帮助到大家。

Python培训班

  1、print 调用 Python 中底层的什么方法

# print 方法默认调用 sys.stdout.write 方法,即往控制台打印字符串。

  2、输入一个字符串, 返回倒序排列的结果 如: abcdef, 返回 fedcba

# 法1
name = "hello yuan"
print(name[::-1])

# 法2
name = "hello yuan"
tmp = list(name)
tmp.reverse()
print(''.join(tmp))

  3、将 ‘python is shell’ 转为 ‘nohtyp si llehs’

s = 'python is shell'
print(' '.join(map(lambda x: x[::-1], s.split(' ')))) # nohtyp si llehs

  4、字符串a = “not 404 found 张三 99 深圳”,每个词中间是空格,用正则的方法,最终输出"张三 深圳

import re
a = "not 404 found 张三 99 深圳"
res = re.findall('[\u4e00-\u9fa5]{2}', a)
print(' '.join(res))  # 张三 深圳

  5、_dict = {‘a’: 1, ‘b’: 2, ‘c’: 3},要求根据value值从大到小输出key

_dict = {'a': 1, 'b': 2, 'c': 3}
print(sorted(_dict.keys(), key=lambda x: _dict[x], reverse=True))  # ['c', 'b', 'a']

  6、将两个列表[1, 5, 7, 9],[2, 2, 6, 8]合并为[1, 2, 2, 5, 6, 7, 8, 9]

  7、如何实现[‘1’, ‘2’, ‘3’]变成[1, 2, 3]

l = ['1', '2', '3']
print(list(map(int, l)))  # [1, 2, 3]

  8、模块互导

  现在有b、c两个模块,且各自的代码如下:

# c.py  
import b  
def foo(): ...  
b.foo()    # AttributeError: module 'b' has no attribute 'foo'
# b.py  
import c  
def foo(): ...  
c.foo()    

# 正如上面例子所示,在模块c中导入模块b,在模块b中导入模块c。此时我们运行模块c,会发生什么样的事情?

  9、xrange和range的区别?

  10、对数值1.3425四舍五入保留2位小数点

  11、一条语句把 L=[(1,2), (3,4)] 转换成 [(1,3),(2,4)],可以写下不同的方法

  12、从0-99这100个数中随机取出10个, 要求不能重复, 可以自己设计数据结构

import random
li = range(1, 101)
print(random.sample(li, 10))

  13、a=[1, {'a':12}]; b=a; a[1]['a']=1;print(b) 输出什么? 并且简述下原因

  14、短路计算

v1 = 1 or 3
v2 = 1 and 3
v3 = 0 and 2 and 1
v4 = 0 and 2 or 1
v5 = 0 and 2 or 1 or 4
v6 = 0 or False and 1

  15、ascii、unicode、utf-8、gbk 区别?

  16、python的三元运算

a, b = 1, 2
result = True if a > b else False
print(result)  # False

  17、a = range(10),a[::-3] 的结果是

a = range(10)
print(a[::-3])  # range(9, -1, -3)
print(list(a[::-3]))  # [9, 6, 3, 0]

  18、Python中哪些是可变类型 ,哪些是不可变类型

  19、解释下Python的深浅拷贝

  20、

l1 = [1,2,3,["yuan","alvin"]]
l2 = l1[:]
l2[1] = 200
print(l1)
l2[3][0] = "张三"
print(l1)

  21、一行代码实现1-100的求和

print(sum(range(1, 101)))  
print((1 + 100) * 100 // 2)  # 等差数列求和公式
print(sum([i for i in range(1, 101)]))

  22、列表去重

li1 = [1, 1, 2, 3, 2, 5]
# print(list(set(li1)))

  23、如何能有t1,t2得到t3

t1 = ('a', 'b', 'c', 'd', 'e')
t2 = (1, 2, 3, 4, 5)
t3 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
# res = dict(zip(t1, t2))

  24、一行print出1~100偶数的列表, (列表推导式, filter均可)

print([i for i in range(1, 101) if i % 2 == 0])
print(list(filter(lambda x: x % 2 == 0,range(1,101))))

  25、

def add(s, x):
    return s + x

def gen():
    for i in range(4):
        yield i

base = gen()
for n in [1, 10]:
    base = (add(i, n) for i in base)

print(list(base))

  26、如何对一个列表去重后再由大到小排序,l=[1,2,56,31,2,44,31,100,18]

print(sorted(list(set(l)), reverse=True))

  27、请实现一个装饰器, 限制该函数被调用的频率, 如10秒一次

  28、请合并下面两个字典 a = {“A”:1,“B”:2},b = {“C”:3,“D”:4}

a.update(b) 

  29、请至少列举5个 PEP8 规范(越多越好)

# 缩进:使用4个空格的缩进,不要使用制表符(Tab键),禁止空格与Tab键混用。

# 换行:折行以确保其不会超过79个字符。这有助于小显示器用户阅读,也可以让大显示器能并排显示几个代码文件。

# 空行:使用空行分隔函数和类,以及函数内的大块代码。顶级函数间空2行,类的方法之间空1行,同一函数内的逻辑块之间空1行,文件结尾空一行。

# 注释:如果可能,注释独占一行。避免逐行添加注释,避免没有一个注释。

# 空格:运算符周围和逗号后面使用空格,但是括号里侧不加空格,如:a = f(1, 2) + g(3, 4)。

# 导入格式:每个导入独占一行,导入放在文件顶部,位于模块注释和文档字符串之后,模块全局变量和常量之前。导入应该按照从最通用到最不通用的顺序分组(标准库 -> 第三方库 -> 自定义库),每种分组中, 应该根据每个模块的完整包路径按字典序排序,忽略大小写。不要使用 from xxx import * 这种语法。

# 变量命名:尽可能的使用有意义的变量名,词能达意。下划线命名法和驼峰命名法。包名、模块名、函数名、方法、普通变量名全部使用小写,单词间用下划线连接。类名、异常名使用 首字母大写(CapWords ) 的方式, 异常名结尾加 Error 或 Wraning 后缀。自定义的变量名、函数名不能和标准库中的函数名重名。

  30、如何交换字典 {“A”:1,“B”:2}的键和值

 {v: k for k, v in dict.items()}  # 字典推导式

  31、Python垃圾回收机制

# python采用的是以引用计数为主,以分代回收和标记清除为辅的垃圾回收机制
    
# 1 引用计数
"""
在python中,每创建一个对象,那么python解释器会自动为其设置一个特殊的变量,这个变量称为引用计数(初始值默认是1)。一旦有一个新变量指向这个对象,那么这个引用计数的值就会加1。如果引用计数的值为0。那么python解释器的内存管理系统就会自动回收这个对象所占的内存空间,删除掉这个对象。
引用计数+1的情况:
    对象被创建,例如a = "yuan"
    对象被引用,例如b = a
    对象被作为参数,传入到一个函数中,例如fun(a)
    对象作为一个元素,存储在容器中,例如data_list=[a,b]
引用计数-1的情况:
    对象的别名被显式销毁,例如del a
    对象的别名被赋予新的对象,例如a = 24
    一个对象离开它的作用域,例如func函数执行完毕时,func函数中的局部变量(全局变量不会)
    对象所在的容器被销毁,或从容器中删除对象
"""
# 2 分代回收
"""
既然已经有引用计数了,那么为什么还要提出分代回收呢?原因就是引用计数没办法解决“循环引用”的情况。
a = ["yuan", ]   # 语句1
b = ["rain", ]    # 语句2
a.append(b)          # 语句3
b.append(a)          # 语句4
# 此时对象的值:a = ["yuan", b]   b = ["rain", a]
del a                # 语句5
del b                # 语句6
# 执行完语句5和语句6是希望同时删除掉a对象和b对象
    
在执行"del a"语句之后,只是删除了对象的引用,也就是此时a变量这个名字被删除,也就是此时对象["yuan",b]的引用计数减1;执行"del b"语句也是同样的情况。但是,此时,由于显式指向它们的变量已经不存在了,所以也没办法删除了,就会导致它们一直存在于内存空间中。 这就是循环引用出现的问题。 此时,单靠引用计数没办法解决问题。所以便提出了分代回收
    
注意:在分代回收中,如果某对象的引用计数为0,那么它所占的内存空间同样也会被python解释器回收。
    
a、此时在python中每创建一个对象,那么就会把对象添加到一个特殊的“链表”中,这个链表称为"零代链表"。每当创建一个新的对象,那么就会将其添加到零代链表中。当这个"零代链表"中的对象个数达到某一个指定的阀值的时候,python解释器就会对这个"零代链表"进行一次“扫描操作”。这个“扫描操作”所做的工作是查找链表中是否存在循环引用的对象,如果在扫描过程中,发现有互相引用的对象,那么会让这些对象的引用计数都减少1。此时,如果某些对象引用计数变成0,那么就会被python解释器回收其所占用的内存空间;如果对象的引用计数仍然不为0,那么会把此时存活的对象迁移到“一代链表”中。
    
b、同样,python解释器也会在一定的情况下,也扫描“一代链表”,判断其中是否存在互相引用的对象。如果存在,那么同样也是让这些对象的引用计数都减少1。此时,如果某些对象引用计数变成0,那么就会被python解释器回收其所占用的内存空间;如果对象的引用计数仍然不为0,那么会把此时存活的对象迁移到“二代链表”中。
    
c、同样,python解释器也会在一定的情况下,也会扫描"二代链表",判断其中是否存在互相引用的对象。如果存在,那么同样也是让这些对象的引用计数都减少1。此时,如果某些对象引用计数变成0,那么就会被python解释器回收其所占用的内存空间;如果对象的引用计数仍然不为0,那么会把此时存活的对象迁移到一个新的特殊的内存空间。此时重新进行"零代链表 -> 一代链表 -> 二代链表"的循环。
    
这就是python的分代回收机制。
"""
    
# 标记清除
"""
那么既然已经有分代回收了,那么为什么又要提出标记-清除呢?
原因就是分代回收没办法解决“误删”的情况。
a = ["yuan", ]   # 语句1
b = ["rain", ]    # 语句2
a.append(b)          # 语句3  
b.append(a)          # 语句4  
# 此时对象的值:a = ["yuan", b]   b = ["rain", a].   ["yuan", b] 、["rain", a]的引用计数都为2
del a                # 语句5
# 此时["yuan", b]的引用计数为1, ["rain", a]的引用计数为2
# 执行完语句5只希望删除a对象,保留b对象
    
如果按照分代回收的方式来处理上述语句。那么,python解释器在执行完语句5之后。在一定的情况下进行查找循环引用对象的时候,会发现此时["rain", a]对象和["yuan", b]对象存在互相引用的情况。所以此时就会让这两个对象的引用计数减1。此时,["yuan", b]对象的引用计数为0,所以["yuan", b]对象被真正删除,但是其实此时["rain", a]对象中是有一个变量引用原来的["yuan", b]对象的。如果["yuan", b]对象被真正删除的话,那么此时时["rain", a]对象中的a变量就没有用了,就没有办法访问了。但是其实我们是希望它有用的,所以这个时候就出现“误删”的情况了。所以此时就需要结合“标记-清除”来解决问题了。
    
标记-清除:
此时同样是检测链表中的相互引用的对象,然后让它们的引用计数减1之后;
但是此时会将所有的对象分为两组:死亡组(death_group)和存活组(survival_group),把引用计数为0的对象添加进死亡组,其它的对象添加进存活组;
此时会对存活组的对象进行分析,只要对象存活,那么其内部的对象当然也必须存活。如果发现内部对象死亡,那么就会想方设法让其活过来,通过这样子就能保证不会删错对象了。
    
题目的重新分析:
  在检查死亡组的时候,会发现["rain", a]对象中的a所指向的对象存在于死亡组中,所以就会想方设法让其复活,此时就能够保证["rain", a]对象中所有的对象都是存活的。
    
"""

  32、实现一个反转整数的函数,例如 -123 –> -321

def reverse_str(value):
    if value > -10 and value < 10:
        return value
    val_str = str(value)
    if val_str[0] != "-":
        val_reverse = int(val_str[::-1])
    else:
        # -123
        val_reverse = -int(val_str[1:][::-1])
    return val_reverse
    
print(reverse_str(112))

  33、Python是如何进行内存管理的?

  34、is和==的区别

  35、合并所有二维列表元素到一个列表:l = [[1, 2], [3, 4], [5, 6]]

print([j for item in l for j in item])

  36、输入某年某月某日,判断这一天是这一年的第几天?

import datetime
date01 = datetime.date(2011,12,31)
date02 = datetime.date(2012,12,12)
# print(date.strftime("%j"))
print(type(date02-date01))
print((date02-date01).days)

  37、统计一段字符串中每个字符出现的次数,比如abcaabccab

s = "abcaabccab"
print(s.count("ab"))
dic = {}
for i in s:
    dic[i] = dic.get(i,0)+1
print(dic)

  38、如何判断一个对象是否可调用

  callable

  39、__str__和__repr__的区别

 # __str__ 的返回结果可读性强。也就是说,__str__ 的意义是得到便于人们阅读的信息
 # __repr__ 存在的目的在于调试,便于开发者使用
    
 # 案例1:
 class A():
...     def __str__(self):
...         return "str"
... 
...     def __repr__(self):
...         return "repr"
... a = A()
a
repr
print(a)
str
    
# 案例2:
import datetime
date = datetime.datetime.now()
print(str(date))  # '2021-05-21 12:04:02.671735'
print(repr(date)) # 'datetime.datetime(2021, 5, 21, 12, 4, 2, 671735)'
    
# 案例3:
import json
    
dic = {"name":"yuan","age":23}
data = json.dumps(dic)
print(str(data))
print(repr(data))
    

  40、什么是c3算法?

  41、什么是断言(assert)?应用场景?

  42、如何最快读取5个G的文件的行数

  43、列举你了解的所有Python2和Python3的区别?

# Python2默认ASCII编码方式,Python3默认的编码方式是UTF-8。
# python2要求包必须有init文件,python3去除了一硬性要求
# python3的range不再返回列表,而是一个可迭代的range对象 
# 去除print语句,加入print()函数实现相同的功能。
# 输入的区别。从键盘录入一个字符串,python2中是 raw_input( "hello world" ),python3则是 input( "hello world" )。
# 在Python 3.x中取消了经典类,默认都是新式类,而且没必要显式的继承object,可是在Python2.x中,默认都是经典类,只有显式继承了object才是新式类。

  44、实现一个Singleton单例类, 要求遵循基本语言编程规范(用尽量多的方式)。

  老男孩IT教育针对企业用人需求专门设置定制化Python课程,学员无基础也可以学习,所有课程都是老师团队研发成立,引用了大型企业项目实战教学,全程采用七位一体授课模式,让学员边学边积累经验。

  推荐阅读:

  Go语言WaitGroup!老男孩GO语言培训班

  如何入门学习Python爬虫?老男孩Python课程怎么样?

  Python入门学习教程之seek与tell方法!

本文经授权发布,不代表老男孩教育立场。如若转载请联系原作者。