python面试题
1.简述列举了解的编程语言及语言间的区别?
我了解python,java和c和go
简单的说,python省去了java和c 的大括号,分号
python使用时更加简洁,方便,和易阅读
python是解释型语言,不需要编辑,java和c 需要编译,但是开发周期长,python使用起来效率比java和c低,但如果不是特别注重延迟的项目,用python更加合适
python是开源的,应用广泛,可移植性强,是可嵌入的解释型编程语言
2.列举Python2和Python3的区别?
python3不兼容python2,但是python2.7都兼容
首先python2不支持中文用的是ASCII,python3支持,用的是utf8
python2和python3的range不同,2中返回一个列表,3中返回一个迭代器,更加节省内存
2中print不加括号,3中加括号
2中的raw_input函数是3中的input函数
3.看代码写结果
v1 = 1 or 2
v2 = 3 and 7 or 9 and 0
1
0
布尔值为假的情况:0,0.0,false,[],(),set(),{},None,'',0j
4.比较一下值有什么不同?
v1 = [1,2,3]
v2 = [(1),(2),(3)]
v3 = [(1,),(2,),(3,)]
v1 = v2
v3 是列表中套了三个元组
5.用一行代码实现数值交换
a = 1
b = 2
a,b = b,a
c = a
a = b
b = c
6.Python中单引号、双引号、三引号的区别?
单引号 == 双引号,里面写字符串内容
三引号里面写函数注释、文档注释,也可以是多行的字符串
7.is和==的区别?
is代表的是两个比较的数据内存地址相同
==代表的两个数值相同
8.python里如何实现tuple和list的转化?
tuple(list列表)
list(tuple列表)
9.如何实现字符串name=老男孩
的反转?
print(name[::-1])
10.两个set如何获取交集、并集、差集?
set1 = {1,2,3}
set2 = {3,4,5}
# 交集
set = set1 & set2
# 并集
set = set1|set2
# 差集
set = set1 - set2
# 对称差集
set = set1 ^ set2
对称差集是除去相同的所有不同的
11.哪些情况下,y != x-(x-y)
会成立?
非空集合且不为子父关系的两个集合
12.python中如何拷贝一个对象
import copy
name = '老男孩'
name1 = copy.deepcopy(name)
13.简述赋值、浅拷贝、深拷贝的区别?
赋值就是一个变量对一个对象的映射关系
浅拷贝就是对一个对象的第一层的拷贝
深拷贝就是对一个对象的全部拷贝,独立于源数据
14.pass的作用
当写一个函数或者写一个类的时候,没有想好内部如何写,就用pass占位
15.阅读代码写结果
import copy
a = [1,2,4,5,['b','c']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
a.append(5)
a[4].append('b')
print(b)
print(c)
print(a)
a = [1,2,4,5,['b','c','b'],5]
b = [1,2,4,5,['b','c','b'],5]
c = [1,2,4,5,['b','c','b']]
d = [1,2,4,5,['b','c']]
16.用python实现9*9乘法表
for i in range(1,10):
for j in range(1,10):
print('{}{}={}'.format(i,j,i*j),end=' ')
print()
17.用python显示一个斐波那契数列
def func(n):
if n <= 2:
return 1
return func(n-1) + func(n-2)
lst = [1,1]
for i in range(10):
lst.append(lst[-1] + lst[-2])
print(lst)
def fib(n):
if n <= 2:
return 1
return fib(n-1) + fib(n-2)
18.如何删除列表中重复的值
list = [1,1,1,2]
set_list = set(list)
19.一个大小为100G的文件etl_log.txt,要读取文件中的内容,写出具体过程代码?
with open('etl_log.txt',r,encoding='utf-8')as f:
print(f.readline())
20.a = dict( zip( ('a','b','c','d','e') ,(1,2,3,4,5) ) )请问a是什么
a = {'a':1,'b':2,'c':3,'d':4,'e':5}
21.lambda关键字的作用?
lambda是匿名函数,用于一次性使用的函数
22.*args和**kwargs的作用?
*args用来接收剩余的位置参数
**kwargs用来接收剩余的关键字参数
23.如何在函数中设置一个全局变量
global 变量名
24.filter,map,reduce的作用
filter:过滤数据
map:映射函数,处理映射数据,将可迭代对象中的每个元素执行相应的操作
reduce:计算数据
from functools import reduce
25.什么是匿名函数,匿名函数有什么作用?
匿名函数,顾名思义就是没有名字的函数,由于一些场景,只需要一次性使用函数,如果定义一个函数,会造成资源的浪费,所以需要使用一个匿名函数,用完之后就自动回收了
26.python递归的最大层数?
1000
27.什么是迭代器?什么是可迭代对象?
只要具有__iter__()方法的是就是一个可迭代对象
具有__iter__()和__next__()两个方法的才是迭代器
28.什么是生成器?
迭代器python内置的
生成器是程序员写的一种迭代器
生成器有两种编写方式,一种是推导式方式和函数编写
29.什么是装饰器及应用场景?
装饰器的本质就是闭包
遵循开放封闭原则
-
1.对扩展功能是开放的
-
2.对修改源代码是封闭的
应用:验证用户登录,property类,框架内
在不修改源代码和调用方式的情况下,对函数进行扩展
30.什么是反射及应用场景?
反射通过字符串直接操作类对象,或者模块中的属性方法
hasattr getattr setattr delattr
应用:可以配合用户的操作或者输入,调用其中的成员
31.写一个普通的装饰器
def times(func):
def foo():
print('装饰001')
func()
print('装饰002')
return foo
@times
def func1():
print("被装饰的函数1")
32.写一个带参数的装饰器
def outer(n):
def wrapper(func):
def inner1(*args,**kwargs):
ret = func(*args, **kwargs)
print('装饰器----')
return ret
def inner2(*args,**kwargs):
ret = func(*args,**kwargs):
print('装饰器-----')
return ret
if n == 'i':
return inner1
else:
return inner2
return wrapper
@outer('i')
def func():
print('我是原本的功能,我被修饰了')
func()
33.求结果
def num():
return [lambda x:i*x for i in range(4)]
print([m(2) for m in num()])
6 6 6 6
34.def(a,b=[])这种写法有什么陷阱
开发中不这么写,如果没有特殊需求,这么写直接开掉
35.看代码写结果
def func(a,b=[]):
b.append(a)
return b
v1 = func(1)
v2 = func(2,[10,20])
v3 = func(3)
print(v1,v2,v3)
[1,3]
[10,20,2]
[1,3]
36.看代码写结果
def func(a,b=[]):
b.append(a)
return b
v1 = func(1)
print(v1)
v2 = func(2,[10,20])
print(v2)
v3 = func(3)
print(v3)
[1]
[10,20,2]
[1,3]
37.请编写一个函数实现将ip地址转换成一个整数
如 10.3.9.12 转换规则为:
10 00001010
3 00000011
9 00001001
12 00001100
再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?
str_ip = ''
for i in ip.split('.'):
bin_str = str(bin(int(i)))[2:]
str_ip += bin_str.format(8,'0')
str_ip += ' '
print(str_ip)
38.请查找一个目录下的所有文件(可能存在文件嵌套)。
import os
def getallsize(pathvar):
size = 0
lst = os.listdir(pathvar)
print(lst)
for i in lst:
pathvar2 = os.path.join(pathvar,i)
print(pathvar2)
# 判断是否是文件
if os.path.isfile(pathvar2):
size += os.path.getsize(pathvar2)
# 判断是否是文件夹
elif os.path.isdir(pathvar2):
size += getallsize(pathvar2)
print(size)
return size
pathvar = r"路径"
res = getallsize(pathvar)
# print(res)
39.求结果
import math
print(math.floor(5.5))
5
40.是否使用过functools中的函数?其作用是什么?
用过functools中的reduce,wraps
reduce是计算数值的高阶函数
wraps在装饰器中使用,如果需要保留函数原本的属性,就加上wraps
41.re的math和search的区别?
search 从任意位置开始查找,查找到结束,没有则返回空列表
match 从头开始查看,如果不符合就不继续查找了
import re
findall 返回的是列表
大小w:[每个元素都是字符串的形式]
# \w 字母.数字.下划线.中文 ***
print(re.findall("\w","宝元-alex_dsb123日魔吃D烧饼"))
# \W 不是字母.数字.下划线.中文 ***
print(re.findall("\W","宝元-alex_dsb123日魔吃D烧饼"))
大小d:[每个元素都是字符串的形式]
# \d 匹配数字 ***
print(re.findall("\d","十10⑩"))
#\D 匹配非数字 ***
print(re.findall("\D","十10⑩"))
判断str的开头结尾,查找不到,返回空列表
# 以什么开头 ***
print(re.findall("^a","alex"))
# 以什么结尾 ***
print(re.findall("x$","alex"))
[每个元素都是字符串的形式]
# . 匹配任意一个字符串(\n除外),加re.DOTALL可以显示\n ***
print(re.findall("a.c","abc,aec,a\nc,a,c"))
print(re.findall("a.c","abc,aec,a\nc,a,c",re.DOTALL))
[每个元素都是字符串的形式]
# 区间
print(re.findall('[0-9]',"alex123,日魔dsb,小黄人_229")) ***
print(re.findall('[a-z]',"alex123,日魔DSB,小黄人_229"))
print(re.findall('[A-Z]',"alex123,日魔DSB,小黄人_229"))
[0-9] # 取0-9之前的数字
[^0-9] # 取非 0-9之间的数字
print(re.findall("[^0-9a-z]","123alex456")) ***
# 匹配*左侧字符串0次或多次 贪婪匹配 ***
print(re.findall("a*","alex,aa,aaaa,bbbbaaa,aaabbbaaa"))
# 匹配左侧字符串一次或多次 贪婪匹配 ***
print(re.findall("a+","alex,aa,aaaa,bbbbaaa,aaabbbaaa"))
# 匹配?号左侧0个或1个 非贪婪匹配 ***
print(re.findall("a?","alex,aa,aaaa,bbbbaaa,aaabbbaaa"))
# 指定查找的元素个数 ***
print(re.findall("[0-9]{11}","18612239999,18612239998,136133333323"))
3~8这个区间
print(re.findall("a{3,8}","alex,aaaabbbaaaaabbbbbbaaa,aaaaaaaaabb,ccccddddaaaaaaaa"))
# 分组***
print(re.findall("<a>(.+)</a>","<a>alex</a> <a>wusir</a>"))
# 控制贪婪匹配***
print(re.findall("<a>(.+?)</a>","<a>alex</a> <a>wusir</a>"))
# '查找的元素' 返回的就是这个元素,查不到返回空列表
print(re.findall("\n","alex\nwusir"))
print(re.findall("\t","alex\twusir"))
print(re.findall("\s","alex\tdsbrimocjb"))# \s 匹配空格
print(re.findall("\S","alex\tdsbrimocjb"))# \s 匹配非空格
面试题:
# search 和 match 区别
# search 从任意位置开始查找,查找到结束,没有则返回空列表
# match 从头开始查看,如果不符合就不继续查找了
# group()进行查看
split -- 分割 # [多个分割,需要用列表把分割符号括起来]
print(re.split("[:;,.!#]","alex:dsb#wusir.djb"))
sub -- 替换
s = "alex:dsb#wusir.djb"
print(re.sub("d","e",s,count=1)) # count 计数,控制替换数量
print(re.sub("d","e",s)) # 默认全部替换
compile 定义匹配规则
s = re.compile("\w")
print(s.findall("alex:dsb#wusir.djb"))
返回的就是一个迭代器
s = re.finditer("\w","alex:dsb#wusir.djb")
print(next(s).group())
print(next(s).group())
for i in s:
print(i.group())
\. 没有任意的功能了
装逼网站:http://tool.chinaz.com/regex/
42.用python匹配html tag的时候,<.>和<.?>有 什么区别?
. 除了\n的任意字符
* 量词 代表匹配0次或者任意个
.* 贪婪匹配
.? 非贪婪匹配
43.如何生成一个随机数?
import random
print(random.random())
44.super的作用?
super用来调用父类的方法或属性
解决多继承之间复杂的调用关系使用
45.双下划线和单下划线的区别?
双下划线的是私有变量、方法、或者函数
单下划线是程序员约定俗成的私有方法或变量,不允许修改,但可以继承使用
单下划线的是私有变量
46.@staticmethod 和@classmethod的区别?
一个是静态方法,一个是类方法
静态方法可以被对象和类调用,不需要传递参数
类方法可以被对象和类调用,默认传递参数,调用的这个类
47.实现一个单例模式(加锁)
class obj():
__obj = None
lock = Lock()
def __new__(cls,*args,**kwargs):
with lock():
if not __obj:
cls.__obj = object.__new__(cls)
return __obj
48.栈和队列的区别?
队列先进先出,栈先进后出。
49.以下代码输出是什么?请给出答案和解释。
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
50.参考下面代码片段
class Context:
pass
def do_something(self):
print('我不做任何事情')
def __exit__(self,*args,**kwargs):
pass
def __enter__(self,*args,**kwargs):
pass
with Content() as ctx :
ctx.do_something()
请在Context类下添加代码完成该类的实现
进阶篇
1.如何获取列表中第二大的值?
使用sorted排序后,取倒数第二个值
用max函数算出最大值,pop,然后在max一次
2.简述python内容管理机制
计数器,垃圾回收,内存池
计数器就是一个变量的使用次数被记录,当变量的计数为零时,就会被从内存中释放
垃圾回收使用 分代回收、计数器、标记清除
分代回收就是分为三代
每一代的变量都会有一个阈值,当达到阈值的时候,会被从内存中释放
标记清除就是当一个变量出现自我循环的时候,会被直接清理
内存池就是同一个文件中,有一些初始化就放在内存中的数据,不需要删除
3.简述python的垃圾回收机制
垃圾回收使用 分代回收、计数器、标记清除
分代回收就是分为三代
每一代的变量都会有一个阈值,当达到阈值的时候,会被从内存中释放
标记清除就是当一个变量出现自我循环的时候,会被直接清理
内存池就是同一个文件中,有一些初始化就放在内存中的数据,不需要删除
4.请用两个队列来实现一个栈
"""
栈 : 先进后出,后进先出
队列 : 先进先出,后进后出
"""
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
[a,b,c]
[a,b]
[a]
[]
5.请用python实现一个链表
# 线性表: 相当于一条直线,没有分支
# ### (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)
# print(head.next)
print("<========>")
6.请用python实现链表的逆转
# 2.链表的逆转
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)