python基础面试题--1
python面试基础篇-----1
- 简述列举了解的编程语言及语言间的区别
java:编译型语言
c语言:编译型语言
python:解释型语言
编译型语言和解释型语言的区别
编译型语言
优点:
运行速度快,执行效率高
缺点:
编译时间长,需要根据操作系统环境编译不同的可执行文件
解释型语言
优点:开发效率高,有良好的兼容性,灵活
缺点:运行速度慢,性能上不如编译型语言
-
Python2和python3的区别
-
Python2:源码不统一,源码有重复,python3,源码统一,源码不重复
-
Python2除法的时候返回的是整数(向下取整),python3返回的是浮点数
-
python3中的input获取的是字符串,python2中获取的是数据本身
-
Python3使用的是Unicode,Python2中使用 ASCII 码
-
python3 iter()和_iter_()都有 python2 只有 iter()
-
Python2中没有提供线程池,python3之后解释器才提供了线程池.
-
Python2: python2.2 之前都是经典类,python2.2之后出现了新式类,继承object就是新式类
Python3: 只有新式类,不管你继不继承object都是新式类
-
-
看代码,写结果
v1 = 1 or 2 结果:1 v2 = 3 and 7 or 9 and 0 结果:7 规则: and的运算,都为真才为真,有一个是假就是假 and的运算,都为真的时候选择and后边的内容 and的运算,都为假时选择and前边的内容 or的运算,只要有一个真就是真 or的运算,都为真时选择or前边的内容 or的运算,都为假时选择or后边的内容 非 ---不是 not True = False 优先级: ()>not>and>or
-
比较以下值有什么不同
v1 = [1,2,3] 列表 v2 = [(1),(2),(3)] 列表套元组 v3 = [(1,),(2,),(3,)] 列表嵌套元组
-
一行代码实现数值互换
a = 1 b = 2 a,b = b,a
-
python中单引号,双引号,三引号的区别
单引号、双引号和三引号没区别,只是在同一个字符串中,一种引号只能用一次
三引号还能用作多行注释
-
is和==的区别
is 比较两个对象的id是否相等,==是比较两边的对象是否相等
-
python中如何实现tuple和list的转化
a = (1,2,3,4,5) b = list(a)
-
如何实现字符串
name='老男孩'
反转name = "老男孩" l = reversed(name) print(''.join(l)) 字符串切片 l= name[::-1]
-
两个set如何获取交集、并集、差集
s1 = {"刘能", "赵四", "⽪⻓⼭"} s2 = {"刘科⻓", "冯乡⻓", "⽪⻓⼭"} 交集 s1&s2 两个集合中的共有元素 并集 s1|s2 两个集合中的全部元素 差集 s1-s2 第一个集合中单独的元素
-
那些情况下, y != x - (x-y)会成立?
x,y都为非空集合 且不为子父关系
-
Python中如何拷贝一个对象
使用深拷贝的方式进行拷贝
-
简述 赋值、浅拷贝、深拷贝的区别
赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。 浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变) 深拷贝:创建一个新的对象,并且递归的复制它所包含的对象
-
pass的作用
pass是占位符,保持程序结构的完整性
-
看代码,写结果
import copy a = [1,2,4,5,['b','c']] b = a c = copy.copy(a)浅 d = copy.deepcopy(a) 深 a.append(5) [1,2,4,5,['b','c'],5] a[4].append('d') [1,2,4,5,['b','c','d'],5] print(b) [1,2,4,5,['b','c','d'],5] print(c) [1,2,4,5,['b','c','d']] print(a) [1,2,4,5,['b','c','d'],5]
-
用Python实现9 * 9 乘法表
for i in range(1,10): for j in range(1,i+1): print("%s*%s=%s"%(i,j,i*j),end=' ') print(' ')
-
用Python显示一个斐波那契数列
def fib(n): if n==1 or n==2: return n return fib(n-1) + fib(n-2) n = int(input()) print('斐波那契数列第%s个是'%(n),fib(n)) 方法二: lst = [1,1] for i in range(10): lst.append(lst[-1] + lst[-2]) print(lst) 方法三 a,b = 0,1 for i in range(10): print(b) a,b = b,a+b
-
如何删除列表中重复的值
lst=list(set(list))
-
一个大小为100G的文件etl_log.txt, 要读取文件中的内容, 写出具体过程代码?
with open(etl_log.txt, 'r') as f: for i in f: print(i,end=' ')
-
a = dict(zip(("a","b","c","d","e"),(1,2,3,4,5))) 请问a是什么
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
-
lambda关键字的作用?
lambda是匿名函数,能提高代码的执行效率,增加可读性 lambda 参数 : 返回值
-
*arg
和**kwarg
作用?*arg在定义函数时接受多余的位置参数,**kwarg接受多余的关键字参数 *arg 把多余的位置参数转化为元组 **kwarg 把多余的关键字参数转换为字典
-
如何在函数中设置一个全局变量
使用global global 变量名
-
filter、map、reduce的作用
map 作用:便于对数组中的每个元素进行操作 是用同样方法把所有数据都改成别的 map(func,iterable) => 返回迭代器 lst = [1,2,3] it = map(lambda x : x*3 , lst) print(list(it)) reduce 作用:对数组中的元素进行汇总 是用某种方法依次把所有数据丢进去最后得到一个结果 from functools import reduce # reduce(func,iterable) => 最后计算的值 # [5,4,8,8] => 5488 lst = [5,4,8,8] res = reduce(lambda x,y : x*10 + y ,lst ) print(res , type(res)) filter 作用:过滤 是筛选出其中满足某个条件的那些数据 filter => 过滤数据 iterable : 可迭代对象(range ,容器类型数据 , 迭代器) filter(func,iterable) => 返回迭代器 lst = [1,2,3,4,5] it = filter(lambda x : True if x % 2 == 0 else False , lst ) print(list(it))
-
什么是匿名函数?匿名函数有什么作用
匿名函数:为了解决那些功能很简单的需求而设计的一句话函数 函数名 = lambda 参数 :返回值 作用:能够简化代码,能作为参数传递,提高执行效率,节省空间
-
Python递归的最大层数
官方给出的结果是1000,实测在998左右
-
什么是迭代器?什么是可迭代对象?
含有__iter__和__next__方法 (包含__next__方法的可迭代对象就是迭代器) 具有__iter__方法的就是可迭代对象。
-
什么是生成器
包括含有yield这个关键字,生成器也是迭代器,调动next把函数变成迭代器
-
什么是装饰器及应用场景
能够在不修改原函数代码的基础上,在执行前后进行定制操作,闭包函数的一种应用 应用场景: django的权限验证 计算函数的运行次数和运行时间 插入日志
-
什么是反射及应用场景
反射就是通过字符串的形式,导入模块;通过字符串的形式,去模块寻找指定函数,并执行。利用字符串的形式去对象(模块)中操作(查找/获取/删除/添加)成员 应用场景 django中的类视图
-
写一个普通的装饰器。
def wrapper(func): def inner(*args,**kwargs): res = func(*args,**kwargs) print("and you") return res return inner @wrapper def func(): print("i am fine 3q") func()
-
写一个带参数的装饰器。
def outer(n): def wrapper(func): def inner1(*args,**kwargs): res = func(*args,**kwargs) print("我是大王") return res def inner2(*args,**kwargs): res = func(*args,**kwargs) print("大王叫我来巡山") return res if n == "alex": return inner1 else: return inner2 return wrapper @outer("alex123") # outer("alex123") => wrapper =>@wrapper def func(): print("i am fine 3q") func()
-
求结果
def num(): return [lambda x:i*x for i in range(4)] print([m(2) for m in num()]) 结果[6,6,6,6]
-
def(a, b=[])这种写法有什么陷阱
b身上的默认值是列表,如果使用原来默认的参数,调用func函数 会把几次调用的值都存放在同一个默认列表里
-
看代码写结果
def func(a,b=[]): b.append(a) return b v1 = func(1) [1,3] v2 = func(2,[10,20])[10,20,2] v3 = func(3)[1,3] print(v1,v2,v3) 先加载,后打印
-
看代码写结果
def func(a,b=[]): b.append(a) return b v1 = func(1) print(v1)[1] v2 = func(2,[10,20]) print(v2)[10.20,2] v3 = func(3) print(v3)[1,3]
-
请编写一个函数实现将IP地址转换成一个整数
如 10.3.9.12 转换规则为: 10 00001010 3 00000011 9 00001001 12 00001100 再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ? # 方法一 ip = "10.3.9.12" strvar = "" for i in ip.split("."): bin_str = str(bin(int(i)))[2:] # 总长度是8 原字符串居右 strvar += bin_str.rjust(8,"0") print(strvar) # 把二进制字符串转换成十进制,默认转换时,是十进制 print(int(strvar,2)) # 方法二 ip = "10.3.9.12" strvar = "" for i in ip.split("."): # format 将整型转化成二进制,不够8位的拿0补位 strvar += format(int(i) , "08b") print(int(strvar,2))
-
请查找一个目录下的所有文件(可能存在文件嵌套)。
os.walk() 生成目录树下的所有文件名
-
求结果
import math floor向下取整 ceil向上取整 round 奇进偶不进(n.5时) print (math.floor(5.5)) 5
-
是否使用过functools中的函数?其作用是什么?
functools用于高阶函数:指那些作用于函数或者返回其他函数的函数。通常情况下,只要是可以被当做函数调用的对象就是这个模块的目标。 用于修复装饰器 import functools def deco(func): @functools.wraps(func) # 加在最内层函数正上方 def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @deco def index(): '''哈哈哈哈''' x = 10 print('from index') print(index.__name__) print(index.__doc__) # 加@functools.wraps # index # 哈哈哈哈 # 不加@functools.wraps # wrapper # None
-
re的match和search区别?
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。 re.search 扫描整个字符串并返回第一个成功的匹配。
-
用Python匹配HTML tag的时候,<.>和<.?>有什么区别?
贪婪匹配( <.> )和非贪婪匹配(<.?> ) ? 匹配0个或一个
-
如何生成一个随机数?
import random print(random.random()) # 用于生成一个0到1的随机符点数: 0 <= n < 1.0 print(random.randint(1, 1000)) # 用于生成一个指定范围内的整数
-
super的作用?
用于子类继承基类的方法 按照c3算法的顺序执行 用来解决多继承之间复杂的调用关系
-
双下划线和单下划线的区别?
双下划线是程序规定的私有方法 单下划线是程序员约定的方法
-
@staticmethod和@classmethod的区别?
@staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样 @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。 如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。 而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。
-
实现一个单例模式(加锁)。
import threading import time class Singleton: __instance = None lock = threading.RLock() def __init__(self, name): self.name = name def __new__(cls, *args, **kwargs): if cls.__instance: return cls.__instance with cls.lock: if cls.__instance: return cls.instance time.sleep(0.1) cls.__instance = object.__new__(cls) return cls.__instance def task(): obj = Singleton('x') print(obj) for i in range(10): t = threading.Thread(target=task) t.start() # 执行1000行代码 data = Singleton('a4sdfasdf') print(data)
-
栈和队列的区别?
栈是先进后出 队列是先进先出
-
以下代码输出是什么? 请给出答案并解释。
class Parent(object): x = 1 class Child1(Parent): pass class Child2(Parent): pass print Parent.x, Child1.x, Child2.x 1 1 1 Child1.x = 2 print Parent.x, Child1.x, Child2.x 1 2 1 Parent.x = 3 print Parent.x, Child1.x, Child2.x 3 2 3
-
参考下面代码片段
class Context: def __enter__(self): return self def __exit__(self,exc_type, exc_val, exc_tb): #在最后执行,执行文件关闭的操作 print("asa") def do_something(self): print('123') with Content() as ctx: ctx.do_something() 请在Context类下添加代码完成该类的实现
第二部分 可选题
-
如何获取列表中第二大的值?
sorted()[-2] 所有容器类型都可以通过sorted进行排序
-
简述Python内存管理机制。
Python 是动态类型语言,对象的类型和内存占用都是运行时确定的,一边运行一边解释。 python解释器通过以下三种方式来管理内存 1.对象的引用次数 引用计数特点:如果引用计数如果是0,就把这个值从内存中释放掉 缺点:在维护引用计数时,有可能数据产生循环引用,造成数据不能删除,造成内存泄漏 2.垃圾回收机制 引用计数为主,标记清除和分带回收为辅 标记清除:检测标记该对象,避免出现循环引用不能删除的现象 标记清除就是一样的变量名引用多少次,只需要一次删除就都删掉了 分带回收:把内存中的数据分成三个区域:新生代0,老年代1,永久带2 3.内存池机制
-
简述Python的垃圾回收机制。
Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题。通过“分代回收”(generation collection)以空间换取时间来进一步提高垃圾回收的效率。没有变量引用及回收
-
请用两个队列来实现一个栈。
from queue import Queue class Stack(): def __init__(self): self.master_queue = Queue() self.minor_queue = Queue() def push(self,val): # 入栈 self.master_queue.put(val) def pop(self): # 出栈 # 如果队列中没有任何值,直接返回None if self.master_queue.qsize() == 0 : return None while True: # 当队列总长度为1的时候,循环终止,把最后一个元素拿出来,为了满足栈后进先出的特点 if self.master_queue.qsize() == 1: value = self.master_queue.get() break # 剩下还没有拿出来的元素,暂时放在2号队列中存储 self.minor_queue.put(self.master_queue.get()) """ minor_queue(1) master_queue(2 3 4) minor_queue(2) master_queue(3 4) minor_queue(3) master_queue(4) """ # 交换队列,重新循环,继续去最后一个值,如法炮制 self.master_queue,self.minor_queue = self.minor_queue,self.master_queue return value obj = Stack() obj.push("a") obj.push("b") obj.push("c") print(obj.pop()) # c print(obj.pop()) # b print(obj.pop()) # a print(obj.pop()) # a
方法二:
class Stock: def __init__(self): self.queueA = [] self.queueB = [] def push(self, node): self.queueA.append(node) def pop(self): if len(self.queueA) == 0: return None while len(self.queueA) != 1: self.queueB.append(self.queueA.pop(0)) self.queueA, self.queueB = self.queueB, self.queueA # 交换是为了下一次的pop return self.queueB.pop() if __name__ == '__main__': times = 5 testList = list(range(times)) testStock = Stock() for i in range(times): testStock.push(testList[i]) print(testList) for i in range(times): print(testStock.pop(), ',', end='') [0,1,2,3,4] 4 3 2 1 0
两个栈实现一个队列
class Queue: def __init__(self): self.stockA=[] self.stockB=[] def push(self, node): self.stockA.append(node) def pop(self): if self.stockB==[]: if self.stockA==[]: return None else: for i in range(len(self.stockA)): self.stockB.append(self.stockA.pop()) return self.stockB.pop() if __name__=='__main__': times=5 testList=list(range(times)) testQueue=Queue() for i in range(times): testQueue.push(testList[i]) print(testList) for i in range(times): print(testQueue.pop(),',',end='')
-
请用Python实现一个链表。
next存的是下一个节点的node对象,这个对象有value就是该节点的内容,next就是再下一个节点的对象 # ### (1) 创建链表 class Node(): def __init__(self, value, next): self.value = value self.next = next head = Node("头", None) last = head for i in range(5): # v0 v1 v2 v3 v4 node = Node("v%s" % i, None) last.next = node last = node # 查看链表的关系 print(head.value) print(head.next.value) print(head.next.next.value) print(head.next.next.next.value) print(head.next.next.next.next.value) print(head.next.next.next.next.next.value)
-
请用Python实现链表的逆转。
def reverse_link_list(head): # 要是空的,或者None,直接返回head if not head or not head.next: return head # 获取上一个节点对象 prev_node = None # 获取下一个节点对象 next_node = head.next # 获取当前节点对象 current_node = head while True: # 修改next,所指向的对象 current_node.next = prev_node # 如果下一个阶段对象是None if not next_node: # not None break # 重新获取上一个对象,即把当前丢向单独存一份,以准备第二次循环时插进next属性中 prev_node = current_node # 重新获取当前对象 , 即把下一个对象单独存储起来(下个) current_node = next_node # 重新获取下一个对象,即把下一个对象单独存储起来,所指向的下个新对象赋值给next_node(下下个) next_node = current_node.next return current_node head = reverse_link_list(head) print(head.value) print(head.next.value) print(head.next.next.value) print(head.next.next.next.value) print(head.next.next.next.next.value) print(head.next.next.next.next.next.value)