代码改变世界

python面试题一

2020-02-26 12:03  l-pf  阅读(439)  评论(0)    收藏  举报

1.简述列举了解的编程语言及语言间的区别。
java、c、c++、csharp、go:编译型语言
python、php、js:解释型语言
编译型语言需通过编译器(compiler)将源代码编译成机器码,之后才能执行的语言。一般需经过编译(compile)、链接(linker)这两个步骤。编译是把源代码编译成机器码,链接是把各个模块的机器码和依赖库串连起来生成可执行文件。
优点:编译器一般会有预编译的过程对代码进行优化。因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高。可以脱离语言环境独立运行。
缺点:编译之后如果需要修改就需要整个模块重新编译。编译的时候根据对应的运行环境生成机器码,不同的操作系统之间移植就会有问题,需要根据运行的操作系统环境编译不同的可执行文件。
解释性语言的程序不需要编译,相比编译型语言省了道工序,解释性语言在运行程序的时候才逐行翻译。
优点:有良好的平台兼容性,在任何环境中都可以运行,前提是安装了解释器(虚拟机)。灵活,修改代码的时候直接修改就可以,可以快速部署,不用停机维护。
缺点:每次运行的时候都要解释一遍,性能上不如编译型语言。
强类型语言:
强类型语言,一旦一个变量被指定了某个数据类型,如果不经过强制类型转换,那么它就永远是这个数据类型。你不能把一个整形变量当成一个字符串来处理。
主要语言:Java、C#、Python、Object-C、Ruby
弱类型语言:
数据类型可以被忽略,一个变量可以赋不同数据类型的值。一旦给一个整型变量a赋一个字符串值,那么a就变成字符类型。
主要语言:JavaScript、PHP、C、C++(C和C++有争议,但是确实可以给一个字符变量赋整形值,可能初衷是强类型,形态上接近弱类型)

编译型语言:一次性全部编译成二进制码,再去执行
解释型语言:编译一句,执行一句
python:解释型,简洁高效,容易上手
java:混合型,(jvm、jit编译器)学习成本高,开发周期慢,web方向
c:编译型,属于底层语言,只有面向过程,没有面向对象
c++:编译型,属于底层语言,既有面向过程,又有面向对象
go:编译型,应用在区块链,高并发高可用,游戏方向
2.列举python2和python3的区别?
python2:源码不统一,源码重复,除法的时候返回的是整数(向下取整),python2中的input获取的就是数据本身,整型 长整型,range获取到的是一个列表
python3:源码统一、不重复,除法的时候返回的是小数(浮点数),python3中的input获取到内容都是字符串,全部都是整型,range是自己本身
python2 默认编码ascii 不支持中文
python3 默认编码unicode
python3 iter() iter() he next() next()都有
python2 没有__next__() 其他都要,好像

python2:
1.print "123"
2.range 返回的是 list
3.默认编码 是 ascii
4.两种类:经典类和新式类
经典类:多继承中的搜索原则是深度优先
新式类:多继承中的搜索原则是广度优先
5.除法:结果是整型
6.int,long(长整型)
7.raw_input ==>等价于python3 input
python3:
1.print()
2.range返回的是可迭代对象
3.都是新式类
4.默认编码是 utf-8
5.除法结果是小鼠
6.int
3.看代码写结果
逻辑运算符优先级 () > not > and > or
逻辑短路
and 全真则真,一假则假
or 一真则真,全假则假
v1 = 1 or 2
v2 = 3 and 7 or 9 and 0
1
7
4.比较以下值有什么不同?
v1 = [1,2,3] 列表
v2 = [(1),(2),(3)]列表
v3 = [(1,),(2,),(3,)]列表里是元组
5.用一行代码实现数值交换。
a = 1
b = 2
a,b=b,a

通用
tmp = a
a = b
b = tmp
6.Python中单引号、双引号、三引号的区别?
单双引号没有区别,三引号可以支持跨行
在互相嵌套时需注意:里外不能使用相同的引号
python单引号 双引号 三引号都是字符串且可以进行转义,唯一的差别就是三引号可以显示多行。
7.is和==的区别?
is 是判断两边内存地址是否相同
== 判断两边的值是否相同
is 是指该值的变量都指向同一个内存,即id是否相同
== 是判断数值算法相同
8.python里如何实现tuple和list的转化?
lis=[1,2,3,4,5,6]
x=tuple(lis)
print(type(x),x)
tup=(1,2,3,4,5,6)
y=list(tup)
print(type(y),y)
9.如何实现字符串 name='老男孩'的反转?
print(name[::-1])
10.两个set如何获取交集、并集、差集?
set3 = set1&set2
set3 = set1|set2
set3 = set1-set2
11.那些情况下, y != x - (x-y)会成立?
x,y是两个不相等的非空集合
"""
非空集合且不为子父关系的两个集合
"""
y != x-(x-y)
x = {"a","b","c"}
y = {"b","d"}

if y != x-(x-y):
print("ok")
12.Python中如何拷贝一个对象?
import copy
针对于列表的拷贝,还可以使用[:] , [::],浅拷贝的一种方式

lst1 = [1,2,3]
lst2 = lst1[:]
lst1.append(4)
print(lst2)
赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。
浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数}
深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数}
13.简述 赋值、浅拷贝、深拷贝的区别?

赋值 : 将变量和值在内存中形成映射指向关系

浅拷贝 : 只拷贝第一级里所有的元素 copy.copy

深拷贝 : 为所有层级的元素都单独开辟新空间 copy.deepcopy() (地址:原不可变数据只是暂时的指向,可变的数据独立开辟新空间)

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

14.pass的作用?
占位符
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('d')
print(a) [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"]]
16.用Python实现9 * 9 乘法表。
l=1
i=0
while l<10:
i=1
while i<=l:
if i==l:
print(i,'',l,'=',li)
else:
print(i,'',l,'=',li,end=' ')

    i += 1
l += 1

print(a)

i = 1
while i<=9:
# 这个位置写代码
j = 1
while j<= i:
# "谁""谁"="谁"
print("%d
%d=%2d" % (i,j,i*j),end=" ")
j+=1

# 打印换行
print()	
i+=1

for i in range(1,10):
for j in range(1,i+1):
print("%d%d=%2d" %(i,j,ij),end='')
print()
17.用Python显示一个斐波那契数列。

方法一

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
def fib(n):
if n <= 2:
return 1
# 上一个值 + 上上个值
return fib(n-1) + fib(n-2)
print(fib(6))

a,b = 0, 1
while b<100:
print (b),
a, b = b, a+b
18.如何删除列表中重复的值?
转为集合
list(set(lst))
19.一个大小为100G的文件etl_log.txt, 要读取文件中的内容, 写出具体过程代码?
fp = open("文件名","模式","编码集")
"""
fp 是迭代器
from collections import Iterator,Iterable

在遍历fp时,文件按照一行一行进行读取;

for i in fp:
code ...
20.a = dict(zip(("a","b","c","d","e"),(1,2,3,4,5))) 请问a是什么?
a是字典
强转字典的条件:等长的二级容器,配合强转字典的两个函数 zip , enumerate

zip 拉链

a = dict( zip( ("a","b") , [1,2] ) )
print(a)

enumerate 枚举

a = dict( enumerate( ["a","b"] ))
a = dict( enumerate( ["a","b"] ,start = 10 ))
print(a)
21.lambda关键字的作用?
lambda表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。
lambda 匿名函数 : 用一句话表达只有返回值的无名函数
lambda 参数 : 返回值
22.*arg**kwarg`作用?
动态位置参数
动态关键字参数

*arg 普通收集参数 : 收集多余的没人要的普通实参

**kwarg 关键字收集参数: 收集多余的没人要的关键字实参

23.如何在函数中设置一个全局变量 ?
"""
global 有该全局变量,修改当前变量,没有改全局变量,定义一个全局变量;
"""
def func():
global a
a = 90
func()
print(a)
24.filter、map、reduce的作用?
map 作用是生成一个新数组,遍历原数组,将每个元素拿出来做一些变换然后放入到新的数组中。
filter 的作用也是生成一个新数组,在遍历数组的时候将返回值为 true 的元素放入新数组,我们可以利用这个函数删除一些不需要的元素

"""
三目(元)运算符 True if 条件表达式 else False

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))
"""

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))
25.什么是匿名函数?匿名函数有什么作用?

没有名字的函数就是匿名函数
可以通过 use 关键字获取上下文中的环境变量,减少不必要参数的传入或导出。减少不必要的函数暴露,提高代码的可读性
如果使用匿名函数,该函数仅仅会在被调用处使用,其他地方不会引用到。如果不使用匿名函数,该函数可以在其他地方被引用。从可读性上讲,没有匿名函数可读性高。
26.Python递归的最大层数?
官方说法1000 , 实际测试 994 ~ 1000
import sys
sys.setrecursionlimit(999999) # 修改递归的最大深度
27.什么是迭代器?什么是可迭代对象?
只要具有iter()方法就是一个可迭代对象
具有iter()和next()两个方法就是迭代器

具有__iter__() 和 next()这两个方法的是迭代器

具有__iter__()方法就是可迭代对象

dir(数据) 可以查看该数据的内部系统成员

可迭代对象 => 迭代器 把不能直接被next获取 => 可直接获取到该数据的一个过程

28.什么是生成器?
生成器的本质就是迭代器,可以自定义迭代的逻辑
创建方式两种:
(1)生成器表达式 (推导式) (i for i in range(3))
(2)生成器函数 (含有yield关键字)

29.什么是装饰器及应用场景?
装饰器本质上是⼀个python函数,它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能;
装饰器的返回值也是⼀个函数的对象,它经常用于有切面需求的场景,实现路由传参,flask的路由传参依赖于装饰器,浏览器通过url访问到装饰器的路由,从而访问视图函数获得返回的HTML页面;

装饰器的本质就是闭包

在不修改原有代码的前提下,额外增加新功能就是装饰器

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

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

通过字符串去操作类对象 或者 模块中的属性方法

hasattr getattr setattr delattr
应用: 可以配合用户的操作或者输入,调用其中的成员,api接口中
31.写一个普通的装饰器。
def warpper(f):
def inner(args,**kwargs):
print("被装饰函数执行前")
ret = f(
args,kwargs)
print("被装饰函数执行后")
return ret
return inner
@warpper
def func(*args,
kwargs):
print(f"被装饰的{args,kwargs}")
return "我是func函数"
@warpper
def index(*args,**kwargs):
print(11111)

print(func(1,2,3,4,5,6,7,8,a=1))

闭包:内函数使用了外函数的局部变量,外函数把内函数返回出来的过程叫做闭包
这个内函数叫做闭包函数;
特点:如果内函数使用了外函数的局部变量,那么该变量于内函数发生绑定,延长该变量的生命周期
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()
32.写一个带参数的装饰器。
def auth(argv):
def wrapper(func):
def inner(args,**kwargs):
if argv:
print("我加上功能了!")
func(
args,kwargs)
else:
func(*args,
kwargs)
return inner
return wrapper

@auth("guobaoyuan")
def foo():
print("这是一个点燃")
foo()

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()

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()])

"""
def出现的位置是函数的定义处
函数() 出现的位置是函数的调用处
(1)调用的时候,才会把函数中的代码,从上到下执行一遍,否则不执行
(2)里面的func是一个闭包函数,延长了当前变量i的生命周期,最后一次i的值3,所以再去调用时候拿的3
"""

def num():
lst = []
for i in range(4):
def func(x):
return i*x
lst.append(func)
return lst

lst = num()
print(lst)

lst = [ m(2) for m in num() ]
lst = [ m(2) for m in lst ]
lst = [ i*x for m in lst ]
lst = [3 * 2 for m in lst]
lst = [6,6,6,6]
34.def(a, b=[])这种写法有什么陷阱?
函数的第二个默认参数是一个list,当第一次执行的时候实例化了一个list,第二次执行还是用第一次执行的时候实例化的地址存储,所以三次执行的结果就是 [1, 1, 1] ,想每次执行只输出[1] ,默认参数应该设置为None。
b身上的默认值是列表,如果使用原来默认的参数,调用func函数
会把几次调用的值都存放在同一个默认列表里
"""
默认参数:
如果调用时,用户给实参了,那么使用用户的
如果调用时,用户没给实参,那么使用默认的(早已存在内存中的这个列表)

默认值会提前在内存中驻留,在使用时,才能调取,在定义函数的时候就提前开辟了空间
"""

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)
[1]
v2 = func(2,[10,20])
print(v2)
[10,20,2]
v3 = func(3)
print(v3)
[1,3]
37.如 10.3.9.12 转换规则为:
10 00001010
3 00000011
9 00001001
12 00001100

再将以上二进制拼接起来计算十进制结果:00001010 00000011 00001001 00001100 = ?

ljust 原字符串居左,填充符号

rjust 原字符串居右,填充符号

方法一

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))
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

"E:\串讲基础\day2\test\1.txt"

pathvar = r"E:\串讲基础\day2\test"
res = getallsize(pathvar)

print(res)

方法二

import os

os.walk() => 生成器

pathvar = r"E:\串讲基础\day2\test"
gen = os.walk(pathvar)

for root,dirs,files in gen:
for name in files:
pathvar = os.path.join(root,name)
print(pathvar)
39. 求结果

import math
print (math.floor(5.5))

-6.0

floor ceil round

import math
print(math.floor(5.5))

round n.5 奇进偶不进

print(round(4.5))
print(round(5.5))
print(round(4.52))
40. 是否使用过functools中的函数?其作用是什么?
functools用于高阶函数:指那些作用于函数或者返回其他函数的函数。通常情况下,只要是可以被当做函数调用的对象就是这个模块的目标。
from functools import reduce

在装饰器中使用,如果想要保留原来函数的属性,加上wraps

from functools import wraps

def wrapper(func):
@wraps(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()
print(func)

def abc():

# pass

print(abc)

  1. re的match和search区别?
    match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配;
    也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none。
    """
    match : 必须从字符串的开头进行匹配
    search: 从任意位置开始匹配,匹配到就返回
    只匹配一个
    """
  2. 用Python匹配HTML tag的时候,<.>和<.?>有什么区别?
    贪婪匹配
    非贪婪匹配
    . 除了\n的任意字符
  • 量词,代表匹配0次或者多次,任意个
    .* 贪婪匹配
    .*? 非贪婪匹配
  1. 如何生成一个随机数?
    print(random.randint(1,50))
    选择1-50之间随机的整数
    print(random.random())
    0-1 之间随机小数,不包含1
    print(random.uniform(1,10))
    1- 10 之间随机小数,不包含10

import random
random.random 随机获取 0<= x < 1
random.randrange 随机获取指定范围中的整数,用法上同range
random.uniform 随机获取指定范围中的小数
44. super的作用?
使用super()可以在子类中调用父类的方法或属性

用来解决多继承之间复杂的调用关系使用super

在多继承中,如果出现了多个同名方法
super在调用的时候,会按照mro列表的继承顺序依次调用
类.mro() = > lst
45. 双下划线和单下划线的区别?
单下划线是约定好的私有属性和方法
双下划线是真正的私有属性和方法,除了自己其他人都看不了

class MyClass():
__abc = 90
ppp = 100
"""
封装: 公有public 私有private 受保护的protected
私有: 只能在当前这个类里面使用,不能再子类或者在类外使用
受保护的: 可以在当前这个类或者子类里使用,不能再类外使用
约定俗成在该变量前面加上一个下划线
, 就表示受保护了
"""
46. @staticmethod和@classmethod的区别?
静态方法类似普通方法,参数里面不用self。这些方法和类相关,但是又不需要类和实例中的任何信息、属性等等。如果把这些方法写到类外面,这样就把和类相关的代码分散到类外,
使得之后对于代码的理解和维护都是巨大的障碍。而静态方法就是用来解决这一类问题的。
当我们需要和类直接进行交互,而不需要和实例进行交互时,类方法是最好的选择。类方法与实例方法类似,但是传递的不是类的实例,而是类本身,第一个参数是cls。我们可以用类的实例调用类方法,也可以直接用类名来调用。

一个静态方法,一个类方法
一个静态方法:(无论是对象还是类,都可以调用,不会默认传递任何参数)
一个类方法 :(无论是对象还是类,都可以调用,会默认传递类这个参数)
47. 实现一个单例模式(加锁)。
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(1)
cls.instance = onject.new(cls)
return cls.instance
def task():
obj = Singleton("x")
print(obj)
for i in range(10):
t = threading.Thread(target=task)
t.start()
data = Singleton("dsadasd")
print(data)

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

from threading import Lock
class MyClass(object):
__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 = MyClass()
obj2 = MyClass()
print(obj1,obj2)
48. 栈和队列的区别?
栈就像一个箱子,后放上去的,可以先出来
队列是先进先出,有出口和入口,先进去可以先出来。

栈 : 先进后出,或者 后进先出
队列: 先进先出
49. 以下代码输出是什么? 请给出答案并解释。

```python
class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass
print Parent.x, Child1.x, Child2.x

Child1.x = 2
print Parent.x, Child1.x, Child2.x

Parent.x = 3
print Parent.x, Child1.x, Child2.x
```

1,1,1
1,2,1
3,2,3
50. 参考下面代码片段

```python
class Context:
    pass

with Content() as ctx:
    ctx.do_something()
请在Context类下添加代码完成该类的实现
```

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

class Context():
def enter(self):
return self
def exit(self, exc_type, exc_val, exc_tb):
# 相当于在最后,执行了文件的关闭操作,fp.close()
print("abc123")
def do_something(self):
print(1111)

with Context() as ctx:
ctx.do_something()
print(ctx)

自动实现了关闭操作

with open("文件") as fp:

res = fp.read()