关于Python常见的基础面试题

文章目录

  • 1.Python优缺点
  • 2.进制的函数
  • 3.ASCII码转换的函数
  • 4.浅拷贝和深拷贝
  • 5.命名规范
  • 6.id和==的区别
  • 7.可变类型和不可变类型
  • 8.列表基础
  • 9.元组基础
  • 10.字典基础
  • 11.集合基础
  • 12.字符串基础
  • 13.函数复习
  • 14.内置的一些函数
  • 15.lambda匿名函数
  • 16.推导式
  • 17.面向对象
  • 18.抽象类
  • 19.常见的八个魔术方法
  • 20.反射方法
  • 21.类的常用函数
  • 22.read、readline、readlines区别
  • 23.常见的异常
  • 24.进程、线程和携程
  • 25.迭代器+生成器+可迭代对象
  • 26.闭包和装饰器
  • 27.垃圾回收机制
  • 28.二分查找
  • 29.冒泡排序、选择排序、插入排序
  • 30.排序算法的复杂度
  • 31.Python3和Python2的对比

1.Python优缺点

  • 简单 易学
  • 开发效率高
  • 面向对象
  • 免费开源
  • 可移植性强
  • 可拓展性
  • 含有丰富的第三方库
  • 解释型语言运行比编译型语言慢

2.进制的函数

  • 其他转换为二进制:bin()
  • 其他转换为八进制:oct()
  • 其他转换为十六进制:hex()
  • 其他转换为十进制:int(‘数字串’,进制数),若写一个参数则为转换为10进制

3.ASCII码转换的函数

  • 字符转换为ASCII码:ord()
  • ASCII码转换为字符:chr()

4.浅拷贝和深拷贝

  • 浅拷贝copy.copy(),粗略复制,可变类型的改变会相互影响
  • 深拷贝copy.deepcopy(),完全复制,与原数据没有关系

5.命名规范

  • 数字、字母、下划线组成
  • 长度任意长
  • 不能含有关键字(查看Python关键字的命令keyword.kwlist)

6.id和==的区别

  • id方法比较的是内存地址是否相同
  • ==比较的是值是否相同

7.可变类型和不可变类型

  • 可变类型:列表,字典,集合
  • 不可变类型:数字,字符串,元组

8.列表基础

  • 有序可重复的序列,
  • 列表内部的元素可以是不同类型,这是和数组的区别
  • 增加:
    • [元素1,元素2]
    • append,追加
    • extend或者+,来完成多个列表合并
    • insert ,插入
  • 删除:
    • del ,Python自带方法
    • remove删除,放值
    • pop,弹出
  • 改:list[索引]=新值
  • 操作:
    • +拼接,*重复
    • count数量
    • len长度
    • reverse反转
    • sort排序
    • index求索引

9.元组基础

  • 不可修改的有序序列,但是元组内部的可变类型元素可以修改
  • 可以使用+拼接,*号重复
  • 注意:(3)不算元组,(3,)算元组

10.字典基础

  • 无序序列,key=value形式
  • 创建空字典的方法是dict()
  • 一个字典有同名的key,按最后一个key的值算
  • 增:
    • dict()
    • setdefault方法,只可以添加,不可以覆盖
    • update,多个字典合并,覆盖
  • 删除:
    • pop(key),弹出对于key的值
    • popitem()随机弹出一个
    • clear,清空字典
    • del方法,可以删除一个字典值,也可以删除整个字典
  • 查:
    • items,通过遍历可以查出所有的key和value
    • keys,通过遍历可以查出所有的key
    • values,通过遍历可以查出所有的value

11.集合基础

  • 无序不可重复的序列
  • 创建空集合直接使用{}或者set()
  • 字典转换为集合,会保留key而不是value
  • 添加:
    • add方法直接添加元素
    • update(),将其他的有序列表添加进去自动去重
  • 删除:
    • clear清空
    • remove删除
    • pop弹出
  • 集合的运算
    • 交集:intersection()或者&
    • 反交集:symmetric_difference()或者^
    • 并集:union()或者|
    • 差集:difference或者-

12.字符串基础

  • 切片:str[起始:结束:步长],左闭右开
  • 倒序:str[::-1]
  • len长度
  • count(字符),计算字符在字符串中出现的次数
  • decode解码,先编码才能解码
  • encode编码
  • startwith判断是不是规定字符开始
  • endwith判断是不是规定字符结尾
  • upper将小写变大写
  • lower将大写变小写
  • find查找有没有指定的字符串,如果有返回开始索引,没有返回-1
  • index查找有没有指定字符串,有返回开始索引,没有则报错
  • join(seq)以指定字符串作为分隔符,将seq所有的元素合并为一个新字符串
  • strip去掉空格,或者指定字符
  • replace替换指定字符串
  • maketrans()创建字符映射转换表,实现多个字符替换
  • max返回字符串最大的字母
  • min返回字符串中最小的字母
  • split切割字符串,返回列表

13.函数复习

  • 参数顺序:位置参数,元组参数,默认参数,字典参数

  • 默认参数针对的是形参,关键字参数针对的是实参

  • 默认参数不用可变类型,会发生逻辑错误,而达不到预期结果

  • 返回值return

    • 可以返回多个值
    • return后不写值,默认返回none
    • 作用是为了结束函数和返回内容
  • 命名空间

    • locals,访问局部命名空间
    • globa,访问全局命名空间
  • 作用域及其执行顺序(按顺序介绍)

    • L(Local),局部作用域
    • E(Enclosing),局部作用域找不到找内嵌作用域
    • G(Global),内嵌作用域找不到找全局作用域
    • B(Built-in),全局作用域炸不到找内建作用域

    都找不到就会报错

  • global和nonlocal关键词

    • global可以将局部变量改为全局变量,可以使函数内部改外部的值
    • nonlocal可以修改嵌套函数的变量,使内层函数可以修改外层函数的值

14.内置的一些函数

  • abs(),求绝对值
  • min(序列,key=函数名),求最小值,当传入key时候,按函数算
  • max(序列,key=函数名),求最大值,当传入key时候,按函数算
  • sort(序列,key=函数名),默认升序,传入函数时候,按函数算,会改变原序列
  • sorted同上,但是返回的是新序列,不改变原序列,降序加reverse=True
  • map(函数名,可迭代内容),将迭代内容依次执行函数,并返回结果,返回map对象
  • filter(函数名,可迭代内容),将迭代内容依次执行函数,返回为True的原值,返回filter对象
  • zip(序列1,序列2,序列…),将序列的元素一一对应打包成元组,按最短的长度打包,返回zip对象

15.lambda匿名函数

  • 优点:代码简洁,不增加额外变量
  • 缺点:难于理解,降低可读性,不推荐使用
  • 注意:内部不可以包含循环、return。可以包含if-else

16.推导式

  • 列表推导式:[i for i in list]
  • 字典推导式:{v:k for k,v in a.items()}
  • 集合推导式:{i for i in set}
  • 生成器:(i for i in tuple)

17.面向对象

  • 面向对象三大特征:封装、继承、多态

  • 封装:

    1.使用符号__双下划线
    2.作用:为了保护隐私
    3.可以使用 _类名__属性名 对封装的方法或者变量进行修改,但是不推荐使用
    
  • 继承:

    1.被继承的类叫父类/基类、超类,继承的类叫子类/派生类
    2.子类可以使用父类的方法或者变量,也可以对父类的方法或者变量进行重写
    3.当子类想重写父类的某个方法,但是又想使用父类这个方法的一些变量,可以使用super关键字
    	例如:super().__init_(name)
    4.子类查看父类的方法:__bases__
    5.父类的私有属性不能被子类继承
    6.继承分为多继承和单继承,如果父类门拥有同一个方法,按继承的第一个顺序继承
    7.多继承的本质是使用广度优先算法,我们可以使用mro方法查看继承顺序
    
  • 多态:

    1.Python是弱类型语言,不支持多态
    2.多态的意思就是同样的方法做了不同的事
    

18.抽象类

  • Python从语法层并没有提供像java/c#那样的抽象类支持
  • 通过abc模块的ABCMeta元类和abstacmethod包装器来达到抽象类的效果
  • 抽象类需要重写

19.常见的八个魔术方法

1.__init__方法:在创建对象的时候自动执行,常用来初始化属性
2.__new__方法:在声明对象的时候自动执行,在__init__方法前被调用
3.__str__方法:打印对象的名称时候调用,使用%s也是默认调用str,使用return返回,必须返回字符串,自动   打印return的信息
4.__repr__方法:改变对象的字符串显示,是str方法的备用方法,找不到str调用此方法,可以使用%r方法调用
5.__del__方法:当一个对象在内存被销毁时自动调用,无返回值
6.__call__方法:可以将对象变成函数使用,如a()
7.__eq__方法:可以进行比较
8.__hash__方法:一般和eq配合使用

20.反射方法

  • hasattr:判断是否由此变量,返回bool
  • getattr:获取属性值或者方法
  • setattr:给类或者对象设置属性或者方法
  • delattr:删除类或对象的属性或者方法

21.类的常用函数

1.issubclass():判断一个类是不是其他类的子类
  格式:
   issubclass(被检测类,父类)
   issubclass(被检测类,(父类1,父类2,父类3…))
   返回布尔值,只要符合一个条件是一个的父类,就会返回true
2.isinstance():检测一个对象是否为某个类的对象
  格式:
   isinstance(对象,类)
   isinstance(对象,(类1,类2…))
   返回布尔值,只要一个类是当前对象的类,返回True

22.read、readline、readlines区别

  • read:读取整个文件,放到字符串中;文件非常大无法使用该方法
  • readline:读取整行,包括行结束符,并作为字符串返回; 比readlines慢得多
  • readlines:一次性读取整个文件;自动将文件内容分析成一个行的列表。

23.常见的异常

  • NameError:名字错误
  • ZeroDivisionError:0错误
  • TypeError:类型错误
  • SyntaxError:语法错误
  • IndexError:索引超出序列范围
  • KeyError:请求一个不存在的字典关键字
  • IOError:输入输出错误
  • AttributeError:尝试访问未知的对象属性

24.进程、线程和携程

1.线程

  • 定义:

    • CPU调度的最小单位,有时候也被称为轻量级进程;
    • 标准线程由线程ID+指令指针+寄存器集合+堆栈组成;
  • 特点:

    • 没有独立资源,但是和同属于一个进程的其他线程共享同一个进程的全部资源;
    • 同一个进程中的线程执行并发执行;
    • 线程之间相互制约,因此有三种基本状态(就绪、阻塞、运行);
  • 线程锁:

    • 产生原因: 由于同一个进程中的线程共享资源和数据,因此容易资源争夺或出现脏数据,因此有了锁可以限制某一时候只有一个线程可以访问某个指定的数据;

    • 互斥锁概念: 某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

    • 互斥锁锁的好处:

      • 确保了某段关键代码只能由一个线程从头到尾完整地执行
      • 保证代码正常的情况下,尽量给最少的代码的上锁,因为上锁的代码只能以单线程执行,效率低
    • 互斥锁锁的坏处:

      • 阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了
      • 由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁
    • 互斥锁死锁:

      • 定义:在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
      • 避免死锁:添加超时时间自动释放
  • GIL锁

    • 产生原因:作为解释型语言,Python的解释器必须做到既安全又高效。数据的保护机制是是解释器全局锁GIL。GIL对当前线程状态和为垃圾回收而用的堆分配对象这样的东西的访问提供着保护。
    • **影响:**使我们我们不可随意使用多线程。
  • 线程的通信通过队列

2.进程:

  • 程序执行的最小单位;
  • 每个进程都有自己独立的数据空间,不同进程之间通常是不能共享数据,创建一个进程需要非常大的开销。
  • 进程之间的通信也可以使用队列;
  • 一个进程中至少包含一个线程;

3.协程

  • 线程和进程的操作是由程序触发系统接口,最后的执行者是系统,它本质上是操作系统提供的功能。而协程的操作则是程序员指定的,在python中通过yield,人为的实现并发处理。
  • 存在意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时。协程,则只使用一个线程,分解一个线程成为多个“微线程”,在一个线程中规定某个代码块的执行顺序。
  • 第三方模块: greenlet和gevent。gevent是对greenlet的高级封装,因此一般用它就行。

4.进程线程的区别

  • 建议在IO密集型任务中使用多线程,在计算密集型任务中使用多进程。
  • 进程与进程相互独立,同一个进程中的线程共享该进程的内存空间和数据。
  • 线程启动速度快,进程启动速度慢。
  • 通信都可以通过各自模块的队列进行。
  • 同一个进程中的线程可以操其他线程,但是进程智能操作其他子进程。

25.迭代器+生成器+可迭代对象

可迭代对象

1.实现了__iter__方法的对象就叫做可迭代对象
2.__iter__方法的作用就是返回一个迭代器对象。直观理解就是能用for循环进行迭代的对象就是可迭代对象。比如:字符串,列表,元祖,字典,集合等等,都是可迭代对象。

迭代器

  • 迭代器两个基本方法,iter和next
  • 可以将迭代对象通过iter方法变为迭代器对象,通过next每次输出
  • 特点是可以记住遍历对象的位置,类似队列的机制
  • 当迭代完成,继续next会报出StopIteration异常

生成器

  • 使用了yield的函数被称为生成器,生成器就是一个迭代器
  • 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行next() 方法时从当前位置继续运行。
  • yield和return不可以同时出现

26.闭包和装饰器

闭包

  • 闭包函数必须有内嵌函数

  • 内嵌函数必须要引用外层函数的变量

  • 闭包函数返回内嵌函数的地址

    def fun1():
        name = '张三'
        def inner():
            print(name)
        return inner
    
    f = fun1()
    f()
    
    __closure__判断函数是否为闭包函数
    如果是闭包,会返回一个cell对象
    不是闭包,返回None
    

装饰器

  • 本质上就是以一个闭包函数
  • 在不修改原函数及其调用方式的情况下对原函数功能进行拓展
  • 使用@符号调用

property装饰器

  • 静态属性:@property。作用就是将类中的无参数方法变成属性使用。

27.垃圾回收机制

python采用的是引用计数机制为主,标记-清除分代收集两种机制为辅的策略

  • 引用计数是每定义使用一个对象,引用计数+1,知道为0的时候才会销毁
  • 缺点是具有实时性,简单
  • 但是缺点是维护引用计数消耗资源

28.二分查找

def binary_search(arr, search):
    low, high = 0, len(arr) - 1  # 第一次将最极端的两个索引记下来
    while low <= high:
        mid = (low + high) // 2
        if search < arr[mid]:
            high = mid - 1
        elif search > arr[mid]:
            low = mid + 1
        else:
            return mid
    return None


a = [1, 2, 3, 4, 5, 6, 7, 8, 15, 45, 86]
b = 86
print(binary_search(a, b))

时间复杂度:O(log2n)

29.冒泡排序、选择排序、插入排序

# 冒泡排序,相邻两两对比
def bubbleSort(arr):
    for i in range(len(arr)):
        for j in range(0, len(arr) - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr


print(bubbleSort([64, 34, 25, 12, 22, 11, 90]))

# 选择排序,选择最小的排好,再选择第二个最小的
A = [64, 25, 12, 22, 11]


def select_sore(arr):
    for i in range(len(arr)):
        min_index = i
        for j in range(i + 1, len(arr)):
            if arr[min_index] > arr[j]:
                min_index = j
        arr[i], arr[min_index] = arr[min_index], arr[i]
    return arr


print(select_sore(A))


# 插入排序
def insertionSort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr


arr = [12, 11, 13, 5, 6]
print(insertionSort(arr))

30.排序算法的复杂度

关于Python常见的基础面试题_第1张图片

31.Python3和Python2的对比

  • Python3去除print语句,加入print()函数实现相同的功能。
  • Python2 中/的结果是整型,Python3 中是浮点类型。
  • 字符串存储的区别。python2中字符串以 8-bit 字符串存储,python3中字符串以 16-bit Unicode 字符串存储。存储格式得到了升级。
  • 取值范围的区别。python2中用xrange ,python3中用range。如:python2中的 xrange( 0, 4 ) 改为python3中的range(0,4)。
  • 键盘输入的区别。从键盘录入一个字符串,python2中是 raw_input( “hello world” ),python3则是 input( “hello world” )。

你可能感兴趣的:(面试题)