python面试题

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)

 

重点:

正则,递归

posted @ 2020-02-26 13:05  徐-  阅读(478)  评论(1编辑  收藏  举报