python基础面试题30问(附带答案)

2023-01-31 00:01:00 面试题 答案 附带

1、     闭包

定义:闭包是由函数及其相关的引用环境组合而成的实体(即:闭包=函数+引用环境)(想想Erlang的外层函数传入一个参数a, 内层函数依旧传入一个参数b, 内层函数使用a和b, 最后返回内层函数)

代码:def ExFunc(n):

        sum=n

        def InsFunc():

             return sum+1

          return InsFunc

2、     装饰器

def debug(func):

    def wrapper():

        print "[DEBUG]: enter {}()".fORMat(func.__name__)

        return func()

    return wrapper

 

@debug

def say_hello():

print "hello!"

3、     迭代器

 

1、可以直接作用于for循环的数据类型

  第一类:集合数据类型,如list、tuple、dict、set、str等;

  第二类:generator,包括集合定义generator和带yield的generator(也就是generator function)。

   以上这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象:

generator不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。那么定义来了,可以被next()调用并不断返回下一个值得对象称为迭代器(Iterator)

把list、dict、str等Iterable变成Iterator可以使用iter()函数

 

4、     生成器

为什么使用生成式:

更容易使用,代码量较小内存使用更加高效

5、     描述器

描述器的表现

用到三个魔术方法。__get__()   __set__()  __delete__()

方法签名如下:

object.__get__(self,instance,owner)

object.__set__(self,instance,value)

object.__delete__(self,instance)

Self指指代当前实例,调用者。

Instance是owner的实例。

Owner是属性所属的类。

典型的描述器:@Property

作用:访问类和实例的属性

6、     内置模块

re(正则)、math(数学)、os(系统)、datetime、sys、JSON

sys:

     sys.argv

功能:在外部向程序内部传递参数

sys.exit(n)

功能:执行到主程序末尾,解释器自动退出,但是如果需要中途退出程序,可以调用sys.exit函数,带有一个可选的整数参数返回给调用它的程序,表示你可以在主程序中捕获对sys.exit的调用。(0是正常退出,其他为异常)

sys.path

功能:获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到。

sys.modules

功能:sys.modules是一个全局字典,该字典是python启动后就加载在内存中。每当程序员导入新的模块,sys.modules将自动记录该模块。当第二次再导入该模块时,Python会直接到字典中查找,从而加快了程序运行的速度。它拥有字典所拥有的一切方法。

7、     列表的用法

函数用法:

         cmp :比较两个列表的元素

         len :列表元素个数

         max :返回列表元素最大值

         min :返回列表元素最小值

         list :将元组转化为列表

方法:

     List.append() 在列表末尾添加新对象

     List.count() 统计某个元素在列表中出现的次数

List.extend() 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)

List.index() 从列表中找出某个值第一个匹配项的索引位置

List.insert() 将对象插入列表

List.pop() 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值

List.remove() 移除列表中某个值的第一个匹配项

List.reverse() 反向列表中元素

List.sort() 对原列表进行排序 reverse=False(默认升序)

.join() 将列表转化为字符串

8、     字符串用法

内建函数:

         Capitalize() 字符串第一个大写

Center() 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串

Count(str,beg=0,end=len(string)) 返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数

decode(encoding=’utf-8’) 以 encoding 指定的编码格式解码 string,如果出错默认报一个 ValueError 的 异 常 , 除非 errors 指 定 的 是 'ignore' 或 者'replace'

encode(encoding=’utf-8’) 以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是'ignore'或者'replace'

endswith(obj,beg=0,end=len(string)) 检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.

expandtabs(tabsize=8) 把字符串 string 中的 tab 符号转为空格,tab 符号默认的空格数是 8。

Format() 格式化字符串

Index() 跟find()方法一样,只不过如果str不在 string中会报一个异常

Isalnum() 如果 string 至少有一个字符并且所有字符都是字母或数字则返回 True,否则返回 False

Isalpha() 如果 string 至少有一个字符并且所有字符都是字母则返回 True,否则返回 False

Isdigit() 如果 string 只包含数字则返回 True 否则返回 False.

Lstrip() 截掉 string 左边的空格

Replace(str1,str2,num=string.count(str1) 把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次

Rstrip() 删除 string 字符串末尾的空格.

Split(str=’’,num=string.count(str)) 以 str 为分隔符切片 string,如果 num 有指定值,则仅分隔 num+ 个子字符串

Strip() 在 string 上执行 lstrip()和 rstrip()

9、     排序算法

冒泡排序:时间复杂度O(n^2)

交换排序的一种。其核心思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序记录为止。

for i in range(length):

            for j in range(i+1, length):

                if lis[i] > lis[j]:

                    self.swap(i, j)

选择排序:时间复杂度O(n^2)

通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录进行交换

for i in range(length):

            minimum = i

            for j in range(i+1, length):

                if lis[minimum] > lis[j]:

                    minimum = j

            if i != minimum:

                self.swap(i, minimum)

插入排序:时间复杂度O(n^2)

基本操作是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表

# 下标从1开始

        for i in range(1, length):

            if lis[i] < lis[i-1]:

                temp = lis[i]

                j = i-1

                while lis[j] > temp and j >= 0:

                    lis[j+1] = lis[j]

                    j -= 1

                lis[j+1] = temp

 

希尔排序:时间复杂度O(n^(3/2))

"""希尔排序"""

        lis = self.r

        length = len(lis)

        increment = len(lis)

        while increment > 1:

            increment = int(increment/3)+1

            for i in range(increment+1, length):

                if lis[i] < lis[i - increment]:

                    temp = lis[i]

                    j = i - increment

                    while j >= 0 and temp < lis[j]:

                        lis[j+increment] = lis[j]

                        j -= increment

                    lis[j+increment] = temp

快速排序:时间复杂度O(nlog(n))

快速排序算法的核心思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后分别对这两部分继续进行排序,以达到整个记录集合的排序目的

while low < high:

            while low < high and lis[high] >= pivot_key:

                high -= 1

            self.swap(low, high)

            while low < high and lis[low] <= pivot_key:

                low += 1

            self.swap(low, high)

二分法查找

算法:二分法查找适用于数据量较大时,但是数据需要先排好顺序。主要思想是:(设查找的数组区间为array[low, high])

10、    Socket编程

Socket服务器编程

    主要包括下面的几步:

1.打开socket

2.绑定到一个地址和端口

3.侦听进来的连接

4.接受连接

5.读写数据

Socket客户端编程

    主要包括下面的几步:

  1.打开socket

  2.连接到一个地址和端口

  3.读写数据

Socket类型

   

 

Socket函数

   

  

  

 

 

 

11、    tcp/UDP

TCP的优点: 可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。

TCP的缺点: 慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

 

UDP的优点: 快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击……

UDP的缺点: 不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。

 

小结TCP与UDP的区别:

  1.基于连接与无连接;

  2.对系统资源的要求(TCP较多,UDP少);

  3.UDP程序结构较简单;

  4.流模式与数据报模式 ;

  5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。

什么时候应该使用TCP: 当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如Httphttps、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、ssh QQ文件传输 ………… 什么时候应该使用UDP: 当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 TFTP ……

有些应用场景对可靠性要求不高会用到UPD,比如长视频,要求速率

12、    HTTP/HTTPS协议

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

HTTPS协议的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

区别

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

 

13、    高阶函数

    Map()、filter()、zip()、reduce()、sorted()、lambda函数

 

14、    深/浅拷贝

  浅拷贝:拷贝表面层,更深的层次引用原来地址的

  深拷贝:拷贝所有,内存中开辟新地址

15、    面向对象编程(OOP)

 

16、    元类

    所有类的父类,定义的新类可以看成元类的实例

17、    正则

功能函数:

     compile() 编译正则表达式模式,返回一个对象的模式

     match() 只匹配字符串的开始,如果开始不匹配,函数返回None

     search() 在整个字符串中寻找,找到返回,匹配不成功返回None

     findall() 遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表

finditer() 搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。找到 RE 匹配的所有子串,并把它们作为一个迭代器返回

       贪婪匹配和费贪婪匹配

前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配

      \d   数字:[0-9]

      \D   非数字:[^\d]

      \s   匹配任何空白字符:[<空格>\t\r\n\f\v]

\S   非空白字符:[^\s]

\w   匹配包括下划线在内的任何字字符:[A-Za-z0-9_]

\W   匹配非字母字符,即匹配特殊字符

\A   仅匹配字符串开头,同^

\Z   仅匹配字符串结尾,同$

\b   匹配\w和\W之间,即匹配单词边界匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的'er'。

\B   [^\b]

.    匹配任意除换行符"\n"外的字符(在DOTALL模式中也能匹配换行符

\    转义字符,使后一个字符改变原来的意思

l   匹配前一个字符0或多次

+   匹配前一个字符1次或无限次

?   匹配一个字符0次或1次

 

18、    __new__ 和 __init__的区别

    1、 继承自object的新式类才有__new__

    2、 __new__至少要有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别

    3、 __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类(通过super(当前类名, cls))__new__出来的实例,或者直接是object的__new__出来 的实例

    4、 __init__有一个参数self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

19、    线程、进程和协程

线程:轻量级进程,线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个 进程的其它线程共享进程所拥有的全部资源

使用threading这个高级模块

多个线程访问同一资源时需要加线程lock

获取锁:lock.acquire()

释放锁:lock.release()

进程:进程是一个实体。每一个进程都有它自己的地址空间

创建进程的类:process

协程:一个程序可以包含多个协程,可以对比与一个进程包含多个线程,因而下面我们来比较协程和线程。我们知道多个线程相对独立,有自己的上下文,切换受系统控制;而协程也相对独立,有自己的上下文,但是其切换由自己控制,由当前协程切换到其他协程由当前协程来控制。

优点:IO资源、减少callback的使用

用第三方库 gevent 来支持协程。gevent用到的主要模式是greenlet

20、    内存管理

1、 Python引入了一个机制:引用计数

2、 垃圾回收机制:当引用计数为0时,调用__del__方法

注意:

1、垃圾回收时,Python不能进行其它的任务,频繁的垃圾回收将大大降低Python的工作效率;

2、Python只会在特定条件下,自动启动垃圾回收(垃圾对象少就没必要回收)

3、当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。当两者的差值高于某个阈值时,垃圾回收才会启动。

      3、内存池机制

            Python中有分为大内存和小内存:(256K为界限分大小内存)

1、大内存使用malloc进行分配

2、小内存使用内存池进行分配

3、Python的内存池(金字塔)

 

21、    random.shuffle(lst):将列表中的元素打乱,洗牌

    random.random():生成一个0-1之间的随机浮点数.

    random.uniform(a, b):生成[a,b]之间的浮点数.

22、    实现单例模式

  1. 使用__new__方法

    class Singleton(object):

        def __new__(cls, *args, **kwargs):

            if not hasattr(cls, '_instance'):

                orig = super(Singleton, cls)

                cls._instance = orig.__new__(cls, *args, **kwargs)

           rerurn cls._instance

 

    class A(Singleton):

        pass

 

    # 类A即为单例类

   2、 使用装饰器

     def singleton(cls):

          instance = {}

          def wapper():

              if cls not in instance:

                  instance[cls] = cls(*args, **kwargs)

             return instance[cls]

      return wapper

 

    @singleton

    class C:

        pass

 

  # 类C即为单例类

23、    实现一个斐波那契数列的生成器

    # def fib(n):

    #     a, b = 0, 1

    #     for _ in range(n):

    #         a, b = b, a + b

    #         yield a

    #

    # def main():

    #     for val in fib(20):

    #         print(val)

    # if __name__ == '__main__':

    #     main()

24、    一行带实现1-100之和

    sum(range(0,100))

25、    python中的GIL

26、    列表去重(通过集合set)

27、    Python2和python3的区别

    1、 print

      p2中print当做一个类使用,p3中print当做一个函数使用

    2、 input()

      p2中input接收到的类型为int,p3中input接收到的类型为str

    3、 Unicode

      Python 2 有 ASCII str() 类型,unicode() 是单独的,不是 byte 类型

    4、 不等运算符

      Python 2.x中不等于有两种写法 != 和 <>

      Python 3.x中去掉了<>, 只有!=一种写法

    5、 数据类型

      Py3.X去除了long类型,现在只有一种整型——int,

      新增了bytes类型,对应于2.X版本的八位串

28、    python中的断言

    关键字:assert

    Assert后面跟合法的表达式,当表达式为True是,不做任何操作,为False时回抛出异常,assert可以快速定位代码中的错误

29、    with方法打开文件实现了关闭的功能

30、    linux常用命令

    ls、cd、vim、mkdir、pwd、rm、rmdir、mv、cp、cat、find、head、history、tail、grep、chmod、tar、ps、top、kill、free、

相关文章