Python基础面试

第一题 简述列举了解的编程语言及语言之间的区别.

编译型: 一次性全部编译成二进制码,然后运行

解释型:编译一行,运行一行

1.python 解释型,间接高效,容易上手,各个方向百花齐放

2.java 混合型(JVM,JIT编译器),开发周期慢,web方向

3.c 编译型 属于底层开发,只有面向过程,没有面向对象

4.c++ 编译型 属于底层开发,既有面向过程,还有面向对象

5.go 编译型 应用在区块链,高并发高可用,游戏方向

第二题 列举python2和python3的区别.

python2

1.print "123"
2.range 返回list
3.ascii
4.两种类: 经典类 和 新式类
class Car(): pass       经典类(多继承当中搜索成员时,采用深度优先原则)
class Car(object): pass 新式类(多继承当中搜索成员时,采用广度优先原则)
5.除法 / : 结果是整数
6.int long(长整型)
7.raw_input

python3

1.print("123")
2.range 返回的是可迭代的对象(容器类型数据,range对象,迭代器)
3.默认utf-8
4.都是新式类
5.除法 / :结果是小数
6.int
7.input

第三题 看代码写结果.

逻辑运算符优先级: () > not > and > or

逻辑短路

""" True or 表达式 False and 表达式 True or True => True True or False = True False and False => False False and True => False """

and 全真则真,一假则假 or 一真则真,全假则假

布尔值为假的十种情况:

0,0.0,False,'',(),[],set(),{},0j,None

v1 = 1 or 2 

v2 = 3 and 7 or 9 and 0 v2 = 7 or 0 

print(v1) 为1

print(v2) 为7

""" Number ( int , float , bool , complex )

复数 : 用在数据分析,人工智能

complexvar = 3 + 4j 实数: 3 虚数: 4j j : 如果有一个数,他的平方等于-1,那么这个数就是j,表达高精度的类型,科学家认为有. """

第四题 比较一下值有什么不同?

元组:逗号是区分元组的标识符

a = 1,2,3

print(a, type(a))

a = () # 空元组

a = (1) # 整型

a = ("abc") # 字符串

 v1 = [1,2,3] # 列表

v2 = [(1),(2),(3)] # [int, int,int]

v3 = [(1,),(2,),(3,)] # [tuple,tuple,tuple]

a = 1 # 整型

a = 1,# 元组

print(a,type(a))

第五题 用一行代码实现数值转换.

a = 1 b = 2

1.一行代码

a,b = b,a

2.通过临时变量

a = 1 b = 2

tmp = a a = b b = tmp print(a,b)

第六题 python单引号、双引号、三引号的区别.

单双引号没有区别,三引号支持跨行

互相嵌套的情况下,不要使用相同的引号

"aa"a"a"

'bbb'b'b'

"""

aaa

'''

bbb

'''

"""

第七题 is和==的区别.

is 是判断两边内存地址是否相同 == 判断两边的值是否相同

第八题 python里面如何实现tuple和list的转化.

int float complex bool str list tuple set dict

list(数据) tuple(数据)

第九题 如何实现字符串name=’老男孩‘的反转?

切片 name[start🔚step] 字符串,列表,元组

name[1:5]

第十题 俩个set如何实现交集、并集、差集?

& 交集 intersection

  • 差集

  • difference

  • | 并集 union

  • ^ 对称差集 (抛出交集之外的部分,合在一起组成集合)

  • symmetric_difference

4 & 5

100

101

100

True and False => False <=> 0

set1 = {"赵忠祥","倪萍","赵丽蓉","王文"}

set2 = {"赵忠祥","倪萍","掏粪男孩","蔡徐坤"}

res = set1 ^ set2

print(res)

"""

要求数据是等长的二级容器,并且元素个数2个

lst = [("a",1),["b",2],{"c",3}] print(dict(lst)) """

第11题 那些情况下,y!=x-(x-y)回成立?

y != x - (x-y)

y != y

非空且不为子父关系的两个集合

x = {"a","b","c"} y = {"b","d"}

{"a","b","c"} - {"a","c"} = {"b"}

{"b","d"} != {"b"}

两个集合 , 互为子集父集时,不符合条件

x = {"a","b","c"} y = {"b","c"}

{"b","c"} != {"a","b","c"} - ( {"a","b","c"} - {"b","c"}) "} !={"b","c"} != {"a","b","c"} - {"a"} {"b","c {"b","c"}

两个空集合, 不符合条件

x = set() y = set() set() != set() - (set()-set()) set() != set()

不能确保每次都成功,存在精度损耗

""" x = 5.829999999999999999 y = 3.318888888888888888 print(y != x - (x-y)) print(0.3 == 0.1+0.2) print(1.5 == 0.3+1.2) """

第12题 python如何拷贝一个对象?

import copy 

lst1 = [1,2,3]

1.copy.copy 2.lst.copy 3.切片[:] [::]

lst2 = lst1[:]

lst2 = lst1

lst1.append(4) print(lst2) # [1,2,3]

第13题 简述赋值 浅拷贝 深拷贝的区别?

赋值 : 从右向左看,将变量和值在内存中形成映射指向关系

浅拷贝: 只拷贝第一级容器中的所有元素 copy.copy()

深拷贝: 为所有层级元素都单独开辟空间,进行拷贝 copy.deepcopy()

(地址: 原不可变数据只是暂时指向原来的空间,可变的数据一开始就单独开辟新空间)

""" 可变数据: list set dict 不可变数据: int float bool complex str tuple """

import copy lst1 = [1,2,3,4,[5,6,7,8]] lst2 = copy.deepcopy(lst1) lst1[0] = 100 print(lst1) print(lst2)

print(id(lst1[-1] )) print(id(lst2[-1] ))

第14题 pass的作用

占位

if 表达式: 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('d')

b [1,2,4,5,["b","c","d"],5]

c [1,2,4,5,["b","c","d"]]

a [1,2,4,5,["b","c","d"],5]

第16题 用python实现9*9乘法表

i = 1 while i <= 9 :

# 打印表达式
j = 1
while j<=i:
# %2d 原字符串默认居右 %-2d 原字符串默认居左
print("%d*%d=%2d " % (j,i,i*j) , end="")
j+=1

# 打印换行
print()

i+=1

 

i = 9 while i >= 1:

# 打印表达式
j = 1
while j<=i:
# %2d 原字符串默认居右 %-2d 原字符串默认居左
print("%d*%d=%2d " % (j,i,i*j) , end="")
j+=1

# 打印换行
print()

i-=1

第17题 用python实现一个斐波那契数列。

1 1 2 3 5 8 13 21 ....

方法一

a = b = 1 for i in range(10): print(a) a, b = b, a+b print(a,b)

a,b = 0,1 for i in range(10): print(b) a, b = b, a+b

方法二

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)

1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144

print(fib(5))

""" return s5 return fib(4) [3] + fib(3) [2] fib(3)[2] + fib(2)[1] fib(2) [1] + fib(1) [1] fib(2)[1] + fib(1)[1] """

第18题 如何删除列表中重复的值

list(set(lst))

第19题 一个大小为100G的文件etl_log.TXT,要读取文件中的内容,写出具体过程代码?

第一种

f = open(文件,mode="r",encoding="utf-8") for line in f: # f是迭代器,遍历时,默认按照一行一行进行读取 print(line)

第二种

r => read的单位是字符 rb => read的单位是字节

with open("文件",mode = "r",encoding="utf-8") as fp: # 一次最多读取100个字符 res = fp.read(100) while res: print(res) res = fp.read(100)

第20题 a = dict(zip(('a','b','c','d','e'),(1,2,3,4,5))) 请问a是什么?

'''zip和enumerate返回的是迭代器''' a = dict(zip(("a","b","c","d","e"),(1,2,3,4,5))) print(a)

zip 拉链函数

Iterator 迭代器 Iterable 可迭代对象

from collections import Iterator,Iterable it = zip(("a","b") , [1,2] ) print(it) for i in it: print(i)

res = isinstance(it , Iterator) print(res)

enumerate 枚举函数

it = enumerate(["a","b"])

start 关键字可以指定开始值;

it = enumerate(["a","b"] , start=10)

for i in it:

# print(i)

res = dict(it) print(res)

issubclass 用来判断子父关系,如果是返回True ,否则返回False;

print(issubclass(Iterator,Iterable))

第21题 lambda 关键字的作用?

lambda 匿名函数 : 用一句话来表达只有返回值的函数 lambda 参数 : 返回值

第22题 *arg和**kwarg的作用?

arg 普通收集参数 : 收集多余的没人要的普通实参 **kwarg 关键字收集参数: 收集多余的没人要的关键字实参 位置参数 -> 形参 def func(arg): pass func(1,2,3) func(a=1,b=2,c=3)

第23题 如何在函数中设置一个全局变量?

"""global关键字可以在函数内定义或者修改全局变量""" def func(): global abc abc = 100 func() print(abc)

 

第24题 filter、map、reduce的作用?

filter -> 过滤数据

三目(元)运算符 : 真值 if 条件表达式 else 假值 lst = [1,2,3,43,5,6]

过滤所有的奇数 [一次计算1个]

filter(lambda x : True if x % 2 == 0 else False , lst) filter 会根据return 返回的True 与 False 判定是保留或者舍弃 True => 保留该数据 False => 舍弃该数据,最后返回迭代器

map -> 处理计算数据[一次计算1个]

lst = [1,2,3] it = map(lambda x : x*3 , lst) print(list(it))

from functools import reduce

reduce -> 计算数据[一次计算2个]

lst = [5,6,7,8] => int 5678 res = reduce(lambda x,y : x*10 + y , lst) print(res) """ 5 * 10 + 5 = 56 56 * 10 + 7 = 567 567 * 10 + 8 = 5678 """

第25题 什么是匿名函数?匿名函数有什么作用?

lambda 匿名函数 : 用一句话来表达只有返回值的函数 lambda 参数 : 返回值

第26题 python递归的最大层数?

官方说法1000层: 实测 994 ~ 1000 import sys sys.setrecursionlimit(9999999) # 修改递归最大深度

第27题 什么是迭代器?什么是可迭代对象?

可迭代对象 -> 迭代器 把不能够直接被next获取 -> 可以被next直接获取的过程

for循环底层用的就是迭代器.

next 获取数据时,是单向不可逆过程;

具有iternext 是迭代器

具有iter方法的是可迭代对象

dir(数据) -> 查看该数据对象的内部成员

第28题 什么是生成器?

生成器是特殊的迭代器,可以自定义迭代的逻辑 不是一股脑把数据一次性拿出,而是通过调用,一次只获取一个 创建生成器两种: (1) 生成器表达式 (推导式) gen = ( i for i in range(3) ) (2) 生成器函数 (含有yield关键字) def func(): for i in range(10): yield i

mygen = func()
print(next(mygen))

第29题 什么是装饰器及应用场景?

在不修改源代码的情况下,为原函数扩展新功能->装饰器

装饰器的本质实际上就是闭包

应用: 登录认证,property类,框架(django , flask @app.route("/",methods=["GET","POST"]))

第30题 什么是反射及应用场景?

通过字符串操作类对象 或者 模块中的成员(属性,方法)

hasattr , getattr , setattr ,delattr 应用: 可以配合用户的操作或者输入,调用其中的成员,完成功能;api接口;

 

第31题 写一个普通装饰器

@符功能: (1) 自动把要扩展功能的函数当成参数传递给装饰器 (2) 把装饰器中的新函数拿出来替换旧函数,以完成功能的拓展;

闭包: 内函数使用了外函数的局部变量,外函数把内函数返回出来的过程叫做闭包 里面的内函数叫做闭包函数; 特点: 闭包情况下,内函数使用了外函数的局部变量,延长该部变量的生命周期

def wrapper(func): # 定义处 * 和* 打包变成元组和 字典 def inner(args,kwargs): # 调用处 * 和 解包成函数中的一个个参数,实现调用; res = func(*args,**kwargs) print("okkkkk@") return res

return inner

@wrapper def func(): print("i am fine and you")

func()

第32题 写一个带参数的装饰器

outer 只是单纯的保留参数

def outer(n): # wrapper是装饰器 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 == 1:
return inner1
else:
return inner2

return wrapper

@outer(1) # outer(1) => wrapper 相当于@wrapper def func(): print(" i am a boy ") func()

第33题 求结果

def num():
return [lambda x:i*x for i in range(4)]
print([m(2) for m in num()])

def num(): return [ lambda x:i*x for i in range(4) ] print([m(2) for m in num()])

[ lambda x : i*x for i in range(4) ]

[ func ]

lambda 参数 : 返回值

i*x for i in range(4)

不是函数,因为返回值错了;

func = lambda x : i*x for i in range(4)

种类三种: 列表推导式 集合推导式 字典推导式

推导式

[ lambda x:i*x for i in range(4) ]

原型

def num(): lst = [] for i in range(4): def func(x): # i => 0 1 2 3 return i * x lst.append(func) return lst lst = num() print(lst) """ [ <function num.<locals>.func at 0x000001ED3201D1E0>, <function num.<locals>.func at 0x000001ED3201D268>, <function num.<locals>.func at 0x000001ED3201D2F0>, <function num.<locals>.func at 0x000001ED3201D378> ] """

原型

for m in num(): # 调用函数 , 参数为2 # return i * x => return i * 2 => i是几? m(2) # 6,6,6,6

for i in range(4): pass print(i) # 3 """ 定义函数时,不会执行其中的代码 只有在调用函数时,才会参与执行和运算; """

定义

def func(x) print(x)

调用

func(3)

""" 刚开始定义的时候,没有去执行函数内部的内容,不存在i变量的赋值. 只有在调用的时候,才会去获取此时的i值 而调用时,此时的i值是3,由于遍历已经结束,而i的值处在闭包中,延长该变量的生命周期,可以获取到 return i * x => return 3 * 2 => 6 由于是4个函数,所以是4个6; """

第34题 def(a,b=[])这种写法有什么陷阱?

b参数(默认参数)等于列表,提前在内存中开辟好空间,进行数据的存储 如果用户传递实参,那么使用用户自己的实参值 如果用户没有传递实参,那么使用默认值(提前开辟好空间的列表) def(a, b=3): pass

第35题 看代码写结果

def func(a,b=[]):
b.append(a)
return b
v1 = func(1)
v2 = func(2,[10,20])
v3 = func(3)

def func(a,b=[]): b.append(a) return b

使用默认在内存中开辟好的列表

v1 = func(1) # [1]

[10,20] 一个列表 默认参数[1]也是一个列表

v2 = func(2,[10,20]) # [10,20,2]

v3 = func(3) # [1,3]

v1,v3 指向同一个列表

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)

v1 = [1]
v2 = [10, 20, 2]
v3 = [1, 3]

第37题 请编写一个函数思想将ip地址转换成一个整数。

方法一

ip = "10.3.9.12" strvar = '' for i in ip.split("."): # print(i) bin_str = str(bin(int(i)))[2:] strvar += bin_str.rjust(8,"0") print(strvar)

把二进制字符串转换成十进制

print(int(strvar,2))

方法二

ip = "10.3.9.12" strvar = "" for i in ip.split("."): # print(format(int(i),"08b")) # 8总长度 0用来补齐8位的 b代表二进制; strvar += format(int(i),"08b") print(strvar) # 00001010000000110000100100001100 print(int(strvar,2)) # 167971084

第38题 请查找一个目录下的所有文件(可能存在文件嵌套)。

方法一

import os def getallsize(pathvar): size = 0 lst = os.listdir(pathvar) # print(lst) for i in lst: # 拼接完整的路径 pathvar2 = os.path.join(pathvar,i) # 判断是否是文件 if os.path.isfile(pathvar2): print(pathvar2,"文件") # 累加文件的大小 size+= os.path.getsize(pathvar2) # 判断是否是文件夹 elif os.path.isdir(pathvar2): print(i,"文件夹") size += getallsize(pathvar2)

return size

pathvar = r"E:\串讲python28\day2\ceshi100" print( getallsize(pathvar) ) # 24674

方法二

import os pathvar = r"E:\串讲python28\day2\ceshi100"

gen = os.walk(pathvar) print(gen) size = 0 for root , dirs , files in gen: # print(root) # print(dirs) # print(files) for name in files: pathvar = os.path.join(root,name) size += os.path.getsize(pathvar) print(size) # 24674

第39题 求结果

import math
print (math.floor(5.5))

floor 地板 向下取整

ceil 天花板 向上取整

import math print(math.floor(5.5)) print(math.ceil(5.1))

第40题 是否使用过dunctools中的函数?其作用是什么?

from functools import reduce

在装饰器中使用,保留原函数的属性,避免暴露装饰器的名字;

from functools import wraps

def wrapper(func): @wraps(func) def inner(args,**kwargs): res = func(args,**kwargs) print("雷霆嘎巴,无情哈拉少") return res

return inner

@wrapper def func(): print(1111) return 123

print(func)

<function func at 0x000001F5EA8F5B70>

<function wrapper.<locals>.inner at 0x0000019DCB645BF8>

<function func at 0x00000210C7575BF8>

第41题 re的match和search区别?

 match : 必须从字符串的开头进行匹配 (默认加了^)

search: 从左到右任意位置开始找,找到就返回;

第42题 用python匹配HTML tag的时候,<.>和<.?>有什么区别?

<.> . 除了\n的任意字符

  • ? + {3,10} 都是量词

  • .? 除了\n的任意字符 匹配到0个或者1个

  • .* 贪婪匹配 默认向更多次匹配

  • .*? 非贪婪匹配 默认向更少次匹配

  • .?? 非贪婪匹配 默认向更少次匹配

<.> 除了\n的任意字符 , 个数必须是一个

<.?> 除了\n的任意字符 , 个数必须是一个 或者 0个

<.*?>

第43题 如何生成一个随机数?

import random

random.randrange 随机获取范围内的整数 用法range相同

random.uniform 随机获取范围内的小数

res = random.uniform(1,5)

第44题 super的作用?

super 用来调用父类的相关成员属性和方法,用来解决多继承之间复杂的调用关系

 类.mro() => 调用顺序列表(继承关系) super调用父类相关成员时,参照mro列表中的继承顺序依次调用

第45题 双下滑线和单下划线的区别?

封装: 公有public 私有private 受保护的protected

私有:__ 2个下划线来表达 __sex

受保护:在python 中有约定俗成的写法,在成员的前面加上一个下划线 (可以在继承时使用该成员,无法在类外使用;) _sex

魔术方法/属性: doc init ...

第46题 @staticmethod和@classmethod的区别?

@staticmethod 静态方法

无论是类还是对象,都可以调用,不会默认传递任何参数

@classmethod 类方法

无论是类还是对象,都可以调用,默认传递类这个参数

class Ceshi():

  @staticmethod

  def func1(): # self

  print(111)

@classmethod
def func2(cls):
print(cls)
print(222)

obj = Ceshi()

obj.func1()

Ceshi.func1()

obj.func2()

Ceshi.func2()

第47题 实现一个单例模式(加锁)。

单态(例)模式 : 这个类无论实例化多少次,都有且只有一个对象

目的: 节省内存空间,提高运行效率,应用在多人使用同一个操作类的场景

每生成一个对象,都在内存中占用空间,尤其在执行mysql操作类时

因为多人的使用,创建出多个对象,而对象本身不会额外增加新成员,只做单纯的成员调用

那么就可以使用单态模式;  

from threading import Lock

class SingleTon():

  # 防止类外直接调用obj成员,对他进行保护,所以用私有

  obj = None

  lock = Lock()

# 控制对象的创建
def __new__(cls,*args,**kwargs):
	with cls.lock:
		if not cls.__obj:
			cls.__obj = object.__new__(cls)
		return cls.__obj

obj1 = SingleTon()

obj2 = SingleTon()

obj3 = SingleTon()

print( id(obj1) , id(obj2) , id(obj3) )

第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题 一下代码输出是什么?请给出打哪并解释。

面向对象的上下文管理, with语法的具体实现

class Context: # 在使用with语法时,自动触发,功能返回对象

  def enter(self):

    return self

# 在执行完with语法之后,自动触发,用来做收尾操作
def __exit__(self, exc_type, exc_val, exc_tb):
print("关闭文件 f.close() ")

def do_something(self):
print("我是做点什么~")

with Context() as ctx:

   ctx.do_something()

附加题:

(1) 如何获取列表中第二大的值

lst = [1,2,3,4,5,5,5,5,5,5,5,5] setvar = set(lst)

列表.sort 类型有局限性,只能是列表,基于原有列表进行修改

sorted 容器类型数据皆可以,返回新列表

lst = sorted(setvar) print(lst) # [1, 2, 3, 4, 5]

res = lst[-2] print(res)

print(sorted("abzzcdefg"))

(2) 简述python内存管理机制。

(3) 简述python的垃圾回收机制。

计数器,垃圾回收,缓存池

1.计数器

a = 100 (100这个值计数为1,被引用过1次) b = a (100这个值计数为2,被引用过2次) del b (100这个值计数为1,被引用过1次,100本身不会被删掉) del a (100这个值计数为0,被引用过0次,100本身被删掉)

2.标记清除 (用来辅助计数) 分带回收

标记清除 :应对解决循环引用的情况,避免删不掉 第0代 新生代 第1代 老年代 第2代 永久代

分代回收 import gc print(gc.get_threshold()) (700, 10, 10)

# 700 新增的对象-消亡对象 == 700 触发分代回收,检测垃圾数据
# 10 当第0代对象检测的次数达到10次,会触发第0代和第1代数据的检测和回收
# 10 当第1代对象检测的次数达到10次,会触发第0代和第1代,2代所有数据的检测和回收

3.缓存池

"""避免频繁的创建或者销毁变量影响效率,提前缓存一些数据在内存中提升速度;"""
1.小数据池-5 ~256,常驻内存 (多个文件之间的)
2.共用数据,常驻内存       (一个文件之内的)
3.使用intern,指定驻留内存
from sys import intern
a = intern("你好sfsdf" * 5)
b = intern("你好sfsdf" * 5)
print(a is b)
posted @ 2020-07-23 17:23  郝雲凯  阅读(328)  评论(0)    收藏  举报