沛齐的315面试题基础部分解答(一)

原题链接:https://www.cnblogs.com/wupeiqi/p/9078770.html

部分图片是从其他博客上整理出来的,时间有些久了当初是写在word上的忘记参考出路了,有些答案我也不知道是否回答准确,如有错误还请提出,谢谢

基础部分

1.简述解释型和编译型编程语言?

 解释型语言在运行之前不会有编译过程,由解释器在运行的过程中解释运行的常见的解释型语言还有PHP、JS、ruby等等。

 编译型语言在运行之前需要使用编译器编译成机器码,计算机就可以直接运行编译过后的文件了。

一般来说编译型语言要比解释型语言运行速度要快的,应为解释型语言每执行一次就需要翻译一次,效率比较慢。

 

2.Python解释器种类以及特点

      常见的解释器有5个CPythonIPythonPyPyJython、IronPython.

      CPython是官方版本的解释器,由C语言编写,运用也是最为广泛的。

      IPython是基于CPython的,只是在交互上做出了进一步的改善,例如代码补全。

      PyPy采用了JIT技术,可以动态编译python程序,提高其工作效率。

      Jython是在Java平台上运行的解释器,可在将python程序编译成Java字节码运行。

      IronPython和Jython类似,运行在.NET平台上。

 

3.位和字节的关系?

位(bit)是计算机存储中的最小单位。只有0、1两种状态

字节(Byte)一个字节由8个bit组成,是计算机数据处理的最小单位。

 

4.使用python进制转换

二进制转换成十进制:v = “0b1111011”
十进制转换成二进制:v = 18
 
八进制转换成十进制:v = “011”
 
十进制转换成八进制:v = 30
 
十六进制转换成十进制:v = “0x12”
 
十进制转换成十六进制:v = 87

5.请编写一个函数实现将IP地址转换成一个整数。

如 10.3.9.12 转换规则为:

      10           00001010

       3            00000011

       9            00001001

      12           00001100

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

6.python递归的最大层数?

Python默认递归的最大层数为998层。

 

7.求结果:
v1 = 1 or 3
v2 = 1 and 3
v3 = 0 and 2 and 1
v4 = 0 and 2 or 1
v5 = 0 and 2 or 1 or 4
v6 = 0 or False and 1

V1 = 1  V2 = 3   V3 = 0   V4 = 1  V5 = 1  V6 = False
(使用and如果第一个条件满足那么结果为第二个条件,如果第一个不满足结果为第一个条件。使用or如果第一个条件满足那么结果为第一个条件,如果第一个条件不满足结果为第二个条件)

 

8.ascii、unicode、utf-8、gbk 区别?

Ascii只占一个字节,其中包含英文字母、数字和一些符号。无法表示其他的文字。

Unicode占两个字节,生僻字符占四个字节。但是如果全是英文字母的话会比较浪费空间。

Utf-8中英文占一个字节中文占三个字节,其他的生僻字占4-6个字节。

GBK占两个字节是中国制定的包含大部分汉字和其他的一些符号。

9.三元运算规则以及应用场景?

Python的三元运算格式为res = 值1 if 条件 else 值2 当条件满足时返回值1否则返回值2。

可以用于只存在两种结果的if判断语句中。

 

10.列举 Python2和Python3的区别?

  1. Print函数:2中不需要括号将输出语句括起来,3中需要使用()
  2. 编码:Python3源码文件默认使用utf-8编码,支持中文
  3. 除法运算:
    首先是'/'  :
        python3:   1 / 2 = 0.5
        python2:   1 / 2 = 0        1.0 / 2.0 = 0.5

         其次是’//’
              Python
3: 1 // 2 = 0
              Python2:    1 // 2 = 0

     4.不等运算符:2中不等于有两种表示!=和<>,3中只有!=

     5.数据类型:3中不支持long类型了只有一种整形int 和2中的long差不多的操作

 

11.用一行代码实现数值交换:a = 1 ,b = 2

(a, b) = (b, a)

12.Python3和Python2中 int 和 long的区别?

Python3中没有long类型只有int但是3中的int操作包含2中的long操作。

13.xrange和range的区别?

Range([start,]stop[,step])更具指定的范围和步长生成一个序列。

Xrange()和range操作一样,不同的是它返回的是一个生成器。

例如当我们使用range(10)的时候返回的是一个[0,1,2,3,4,5,6,7,8,9]的列表。而xrange(10)不会返回一个列表,而是每次调用的时候返回其中的值。这样在生成一个很大的操作的时候xrange的性能会更好。

14文件操作时:xreadlines和readlines的区别?

和上面的range和xrange一样的区别,readlines将文件中读取的数据读取出来生成一个列表存放着,而xreadlines返回的是一个迭代器每次调用的时候返回下一个值。所以对于数据量比较大的时候使用迭代器的方法会更好一些。

15.列举布尔值为False的常见值?

0、None、””、[]、{}

16.字符串、列表、元组、字典每个常用的5个方法?

字符串:isdigit()判断是否只包含数字 islower()判断是否全为小写 isupper()判断是否全为大写  strip()去掉首尾空格  split()以指定字符切片

列表:append()在列表后面追加  count()统计次数  pop(index=-1)默认移除最后一个元素并返回  sort()排序  reverse()反向列表中的元素 min()、max()返回最小最大值。

元组:cmp(tuple1,tuple2)比较两个元组元素  len()计算元组元素个数  max()返回最大值  min()返回最小值 tuple(list)将列表转为元组。

字典:get(key,default=None)返回指定键的值,没有返回默认值  copy()返回一个字典的浅复制  update(dict2)将dict2更新到原字典中  value()返回所有值 keys()返回所有键  pop(key)删除并返回指定的key的值   popitem()随机删除并返回一个键值对。

 

17.lambda表达式格式以及应用场景?

Lambda语句中冒号前面的为参数,可以有多个,用逗号隔开。冒号右边的为返回值,如:add = lambda x, y : x + y

   add(1,3) 结果为4

Lambda表达式通常是在需要一个函数,但是又不想费神去命名一个函数的时候使用通常应用在函数式编程中、闭包

 

18.pass的作用?

Pass是空语句,为了保持程序结构的完整性,不做任何操作,一般只用做占位语句。

 

19.*args和**kwargs作用

如果我们不确定往一个函数中传入多少参数,或者我们希望以元组tuple或者列表list的形式传参数的时候,我们可以使用*args。如果我们不知道往函数中传递多少个关键词参数或者想传入字典的值作为关键词参数的时候我们可以使用**kwargs,args、kwargs两个标识符是约定俗成的用法。另一种答法:当函数的参数前面有一个星号*号的时候表示这是一个可变的位置参数,两个星号**表示这个是一个可变的关键词参数。星号*把序列或者集合解包(unpack)成位置参数,两个星号**把字典解包成关键词参数。

 

20.is和==的区别

      is比较的是两个实例对象是不是完全相同的,他们是不是同一个对象,占用的内存地址是否相同。

      ==比较的是两个对象的内容是否相等,内存地址可以不同,内容一样就可以了。

 

21.简述Python的深浅拷贝以及应用场景?

Python的变量只存储了这个变量的内存地址,而不是值的本身,对于像list set dict这种复杂的数据结构来说里面存储的也仅仅是每个元素的地址而已

赋值:变量的每一次初始化都会在内存里面开辟一个新的空间,并将这个内存地址赋值给变量,例如:

给str1两次赋值,两次的内存地址发生改变,第一次赋值hello的时候将hello在内存中的地址给了str1,第二次赋值world的时候再次将world的内存地址给了str1,但是此时hello并没有从内存中消失,只是现在没有变量指向他。当我们再次赋值的时候str1又指向了hello。

深拷贝:

深拷贝可以完全复制原变量的所有数据,我们修改其中一个的时候不会对复制的那份造成影响。

浅拷贝:

不管多么复杂的数据结构,浅拷贝只会copy一层。对于像int float str这种单一的数据是可以独立出来,但是对于更为复杂的数据结构就会出问题,因为在复制的时候只是将列表 字典等的整个的存放地址给复制过来了,并没有复制里面元素的内存地址,这样导致修改的时候会同时发生变化。例如:

 

 

22.Python垃圾回收机制?

Python的垃圾回收机制默认的方式是引用计数法,其原理是为每一个对象维护一个ob_ref字段,用来记录该对象当前被引用的次数,有新的引用指向过来的时候计数加一,引用失效时计数减一,当对象的引用计数为0的时候,对象会被回收,释放内存空间。除了这个还有标记清除法和分代回收。

 

23.Python的可变类型和不可变类型?

数字、字符串、元组是不可变的,列表字典是可变的,对于不可变类型的变量重新赋值的时候实际上是重新创建一个新的对象,原变量指向新的对象内存地址,除浮点型变量之外,对于值相同的变量可能都会指向同一个内存地址。可变类型例如列表在新增一个元素的时候,变量还是指向原来的那个内存地址,只是其中的元素指向发生了改变。

 

24.求结果:
  v = dict.fromkeys(['k1','k2'],[])
 
   v[‘k1’].append(666)
  print(v)
   v[‘k1’] = 777
  print(v)

{'k1': [666], 'k2': [666]}

{'k1': 777, 'k2': [666]}

猜测原因是,在创建v这个字典的时候k1 k2 都指向了同一个空列表,当我们修改了这个列表的内容之后两个会同时发生改变,第二次单独修改k1的时候重新开辟了一个空间并指向新的内存地址。

 

25.求结果:

[6, 6, 6, 6]

解释见:https://www.cnblogs.com/imhurley/p/3898289.html

 

26.列举常见的内置函数?

abs() 绝对值  len()序列长度 divmod()取模 pow()乘方 round()浮点数

 

27.filter、map、reduce的作用?

filter()函数:filter()函数接收两个参数,一个是bool函数,一个是序列,依次将序列中的每一个元素传入到bool函数中,返回值为非零的元素添加到新的列表中。

map()函数:map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回

reduce()函数:三个参数,一个需要两个参数的函数,一个序列,一个初始值,执行顺序为:将序列中的第一个值和初始值进行func处理,然后将结果和序列第二个值处理直到结束。

 

28.一行代码实现9*9乘法表

      print " ".join(" ".join(["%s*%s=%s" %(x,y,x*y) for y in range(1, x+1)]) for x in range(1, 10))  

 

29.re的match和search区别?

Match是从头开始匹配 search从任意位置匹配

 

30.什么是正则的贪婪匹配?

贪婪匹配就死趋于最大长度的匹配

非贪婪匹配就是匹配到结果就好

 

31.def func(a,b=[]) 这种写法有什么坑?

函数的第二个参数是一个list,当第一次执行的时候实例化了一个list,第二次执行的时候还是用的是第一次实例化的那个list

32.如何实现 “1,2,3” 变成 [‘1’,’2’,’3’] ?

  1. 如何实现[‘1’,’2’,’3’]变成[1,2,3] ?

 

34.比较: a = [1,2,3] 和 b = [(1),(2),(3) ] 以及 c = [(1,),(2,),(3,) ] 的区别?

a是一个列表,其中的元素为整数

a和b 的内容一样但是在内存中的地址不同,也就是 a==b 成立 a is b 不成立

c也是一个列表,只不过其中的元素为元组

 

35.如何用一行代码生成[1,4,9,16,25,36,49,64,81,100] ?

     1:list(map(lambda x:x*x ,[1,2,3,4,5,6,7,8,9,10]))

2:list(x*x for x in range(1,11))

 

36.一行代码实现删除列表中重复的值 ?

list1 = list(set(list1))

 

37.如何在函数中设置一个全局变量 ?

使用global声明变量

 

38.logging模块的作用?以及应用场景?

       logging模块是python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、保存路径、日志文件回滚等。可用于记录程序运行状态。

 

39.请用代码简单实现stack 。

class Stack(object):
    # 初始化栈为空列表
    def __init__(self):
        self.items = []

    # 判断栈是否为空,返回布尔值
    def is_empty(self):
        return self.items == []

    # 返回栈顶元素
    def peek(self):
        return self.items[len(self.items) - 1]

    # 返回栈的大小
    def size(self):
        return len(self.items)

    # 进栈
    def push(self, item):
        self.items.append(item)

    # 出栈
    def pop(self, item):
        return self.items.pop()

 

40.常用字符串格式化哪几种?

主要有两种 % 和format

示例1:”%s%d” %(‘hello’,1)

示例2:"i am {} age {} sex:{}".format('alex',38,'male')

             "i am {1} age {1} sex:{2}".format('alex',38,'male')

 

41.简述 生成器、迭代器、可迭代对象 以及应用场景?

生成器:生成器其实是一种特殊的迭代器,生成器一定是迭代器反之不成立,不需要写__iter__()和__next__()方法,只需要一个yield关键字。
例如:斐波那契的例子

def fib():
    prev, curr = 0, 1
    while True:
        yield curr
        prev, curr = curr, curr + prev

>>> f = fib()
>>> from itertools import islice
>>> list(islice(f, 0, 10))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

     生成器表达式:是列表推倒式的生成器版本,看起来像列表推导式,但是他返回的是一个生成器对象而不是列表对象 
    

迭代器:可以被next调用并不断返回下一个值的对象称为迭代器,迭代器内部有一个状态,该状态用于记录当前迭代所在的位置,__iter__()返回迭代器本身,__next__()返回容器中的下一个值。

可迭代对象:但凡可以返回一个迭代器的对象都可以称之为可迭代对象,更为直观点可以使用for循环的对象,如列表,元组,字典,集合,字符串,打开的文件,socket等。

 

42.用Python实现一个二分查找的函数。 
     

43.谈谈你对闭包的理解?

闭包就是在一个外部函数中定义一个内函数,内函数里运用了外部函数的临时变量,并且外函数的返回值是内函数的引用。如下是最简单的一个闭包:

在python中一切皆对象,小到一个变量,大到一个函数一个类都是对象,变量名,函数名类名都是指向内存地址。因此当返回值为一个函数的引用的时候可以跟括号来调用此函数。
一般来说,当一个函数结束的时候,会将临时变量释放掉,但是在闭包中,临时变量会在内部函数中用到,因此在返回内函数的时候会将临时变量和内函数绑定在一起,外函数结束后,在调用内函数的时候依然可以使用外函数的临时变量。每次在调用外函数的时候都会在内存中创建一个内函数,并且返回的是当前的内函数地址,需要知道的的是虽然内函数被重新创建了,但是外函数的临时变量只存在一份,每次创建的内函数都是使用的同一份临时变量。如下两次调用的返回值是不同的

Python中内函数想要修改外函数的临时变量可以使用nonlocal关键字来定义变量,如下:

闭包的应用:装饰器、单例模式

44.os和sys模块的作用?

os 模块提供了一种方便的使用操作系统函数的方法。

sys模块可供访问由解释器使用或维护的变量和与解释器进行交互的函数。

 

45.如何生成一个随机数?
     

 

46.如何使用python删除一个文件?

os.remove(file_path)

os.rmdir(dir_path)

47.面向对象深度优先和广度优先是什么?

Python 中类的多继承分为深度优先和广度优先,新式类会按照深度优先方法查找,金典类会按照广度优先的方式查找。

 

48.面向对象中super的作用?

Super()可以保证公共的父类仅被执行一次。按照MRO的顺序执行原理待更新:

 

49.列举面向对象中带爽下划线的特殊方法,如:__new__、__init__

__doc__  表示类的描述信息

__module__ 表示当前操作的对象在那个模块

__class__ 表示当前操作的对象的类是什么

__init__  构造方法,通过类创建对象时,自动触发执行

__del__ 析构方法,当对象在内存中被释放的时候,自动触发执行

__call__ 对象后面加括号,触发执行

__dict__ 类或对象中的所有成员

__str__ 如果一个类中定义了这个方法那么在打印对象的时候默认输出该方法的返回值

__getitem__、__setitem__、__delitem__ 用于索引操作,如字典。分别表示获取、设置、删除数据

__getslice__、__setslice__、__delslice__分别用于切片操作,如列表

__iter__ 用于迭代器

__new__和__metaclass__

 

50.如何判断是函数还是方法?

根据__call__属性判断: if(hasattr(func,’__call__’)):

利用callable判断: if(callable(func)):

利用isfunction判断:if(isfunction(add)):

51.静态方法和类方法区别?

类方法必须有一个指向类对象的引用作为第一个参数,但是静态方法可以没有任何参数,

 

52.列举面向对象中的特殊成员以及应用场景

 

53.   1、2、3、4、5 能组成多少个互不相同且无重复的三位数

        A53 = 60个

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

其实,反射就是通过字符串的形式,导入模块;通过字符串的形式去模块寻找指定的函数并执行。利用字符串的形式去对象(模块)中操作(查找、获取、删除、添加)成员,是一种基于字符串的事件驱动。

getattr(object, name [,defaukt])函数是python内置函数,用于返回一个对象属性值,若不存在且为设置默认值则触发异常,如果设置了默认值则返回默认值。

 

hasattr(object,name):判断对象object是否包含名为name的特性(hasattr是通过调用getattr()是否抛出异常来实现的)。如果有该属性则返回True否则返回False

setattr(object, name, value):对应函数getattr(),用于设置属性值,或者增加某个属性。


 

 

delattr(object, name):用于删除属性,操作类似不举示例了。

应用:实现一个简单的url路由器的功能,实现动态导入模块

 

55.metaclass作用?以及应用场景?

Metaclass 的实例化结果是类。而class实例化结果是instance,metaclass是创建类的模版,所有的类都是通过他来创建的,这使得我们可以自由控制创建类的过程。实现自由的修改、增加、删除 类或者实例中的方法或者属性。可批量对某些方法使用装饰器,而不需要每次都在方法上面增加@decorator_func。等等

 

56.用尽量多的方法实现单例模式。

单例模式的主要目的是确保某一个类只有一个实例存在,主要的实现方式有以下几种:

1:使用模块。

2:使用装饰器。
      

      
      

 

3:基于__new__方法实现。
      在实例化一个类的时候,首先执行了类的__new__方法,然后执行__init__方法,
在实例化的时候先检查有没有已经实例化过,如果有则返回已经实例化候的对象,否则创建新的。

     4:基于metaclass方法实现
        1.类由type创建,创建类时,type的__init__方法自动执行,类() 执行type的 __call__方法(类的__new__方法,类的__init__       方法)。
        2.对象由类创建,创建对象时,类的__init__方法自动执行,对象()执行类的 __call__ 方法。

 

57.装饰器的写法以及应用场景。

python的装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数和闭包一样,所以装饰器是闭包的一种应用,使用装饰器可以不用在更改原函数的前提下给函数增加新的功能,当有多个装饰器的时候从上到下依次执行。
装饰器的原理:和闭包类似
最简单的一个装饰器

主要用户一些认证功能,日志,授权

 

58.异常处理写法以及如何主动抛出异常(应用场景)
     

     

 

 

59.什么是面向对象的mro

 

60.isinstance作用以及应用场景?
      用来判断一个对象是否是一个已知类型,类似type(),
和type不同的是type()不会认为子类是一种父类类型,不考虑继承关系,而isinstance()会认为子类是一种父类类型,会考虑继承关系。如果要判断两个类型是否相同的时候最好使用isinstance

61.写代码并实现:
       给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
       你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

       Example:
                Given nums = [2, 7, 11, 15], target = 9,
                
Because nums[0] + nums[1] = 2 + 7 = 9,
                return [0, 1]   
       

62.json序列化时,可以处理的数据类型有哪些?如何定制支持datetime类型?

       可处理的数据类型有:字符串、列表、元组、字典、整数,不支持集合。定制支持datetime:首先写一个类:将用于判断是否         为datetime类型的数据格式,如果是则将其转换成字符串类型。再交给json处理。使用的时候指定cls参数即可。
       

63.json序列化时,默认遇到中文会转换成unicode,如果想要保留中文怎么办?
     

 

64.什么是断言?应用场景?

assert断言用来检查一个条件,如果为真那么不做任何事,如果错误则会抛出AssertionError错误并且包含错误信息,应用场景:程序常量,检查逻辑,检查文,档检查约定格式为 assert 语句, 报错输出

原文地址:https://www.cnblogs.com/FanMLei/p/10501010.html