Python面试题

一、语言特性

1.谈谈python和其他语言的区别?

python属于解释性语言,当程序运行时,是一行一行的解释并运行,所以调试代码很方便,开发效率高。

缺点:

运行速度慢。

2.解释型语言和编译型语言特点?

解释:边解释边执行。

编译:编译后再执行。

3.python3和python2的区别?

  • 打印时py2不一定要加括号,而python3需要
  • 输出中文时,py2需要加# -*- encoding:utf-8 -*-
  • input不同
  • 在一群模块文件的集合需要加__init_, py3不一定。

二、编码规范

python中有一个很奇妙的特性,称为文档字符串,他通常简称为docstring

三、数据类型

1.列举python中的基本数据类型

不可变数据类型

  • Number
  • String
  • Tuple

可变数据类型

  • List
  • Set
  • Dictionary

2.python中字符串格式化方式?

  • format()
  • %s占位符

3.单引号、双引号和三引号的区别?

s = 'hello'
s= "hello"
单引号与双引号没有区别,
三引号可以用来加注释,所加注释可以使用__doc__查看

4.del和pop有什么区别?

del操作删除键值对,不返回值;

pop操作删除键值对的同时,返回键所对应的值。

5.函数装饰器有什么作用?

函数装饰器可以在不修改原函数的条件下,为原函数添加额外的功能,例如记录日志、运行功能、缓存等以记录函数运行时间为例,实现一个装饰器?

import time
def time_it(func):
    def wrapper(func):
        start_time = time.time()
        res = func()
        end_time = time.time()
        return start_time - end_time
    return wrapper

6.简述python的垃圾回收机制

  • 引用计数机制:

    python对象的核心是一个结构体。

    PyObject
     typedef struct_object {
     int ob_refcnt;
     struct_typeobject *ob_type;
    } PyObject;
    

ob_refcnt记录了对象的引用次数。当一个对象有新的引用时,ob_refcnt加1,引用它的对象被删除时,ob_refcent减一,当ob_refcnt = 0时,这个对象的生命就结束了,这时,垃圾回收机制就会启动这个对象回收。

优点:简单、实时性高。

缺点:维护引用技术消耗了很多资源,如果出现循环引用,则永远不可能被回收。

  • 标记清除

    从更对象(root)出发,沿着有向边遍历整个图,不可达对象就是需要清理的垃圾对象。这个跟对象就是全局对象,调用栈,寄存器。

  • 分代回收

    虽然标记清除可以回收循环引用的垃圾,但是,回收的频次是需要控制的,如果时时刻刻做标记清除,可以想象,python的程序会非常慢。

    分代回收,根据内存中的对象存活时间将他们分成三代,

7…简述 @classmethod 和 @staticmethod 用法和区别。

一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。而使用@classmethod 和 @staticmethod就不需要实例化。直接类名.方法()来调用。

区别:

  • @staticmethod不需要表示自身对象的self参数和自身类的cls参数,就和使用函数一样。
  • @classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。

如果在@staticmethod中需要调用到这个类的一些属性方法时,只能类名.属性名或类名.方法名。

而@classmethod因为持有cls参数,可以用来调用类法属性,类的方法,实例化对象等,避免硬编码。

8.python中的is和==有什么区别?

is比较的是两个对象的id值是否相等,也就是比较两个对象是否为同一个实例对象,是否指向同一个内存地址。

==比较的是这两个对象的内容是否相等,默认会调用对象的__eq__方法。

9.深拷贝和浅拷贝的区别是什么?

浅拷贝,赋值的时候非递归的调职子对象的引用

深拷贝,赋值的时候递归的复制子对象

10.请阐述代码中经常遇到的 *args, **kwargs 的含义及用法。

这两个是python中的可变参数。*args表示任何多个位置参数,它是一个tuple;**kwargs表示关键字参数,它是一个dict。并且同时使用*args和**kwargs时,必须*args参数列要在**kwargs前

11.python的多线程能用多核cpu吗?

python的多线程不能利用多核cpu。原因是python的解释器使用了GIL,在任意时刻只允许单个python线程运行。无论系统有多少个cpu核心,python程序都只能在一个cpu上运行。

List和Tuples区别

列表元组
可变的,可以被编辑不可变,所以可以用作字典key
比元组慢比列表快(因为支持的操作少)
list=[10,‘C’,20]tuple_1=(10,‘C’,20)
一般表示数据一般表示结构
数组和列表的区别

具有相同的存储数据方式,但是数组中只能包含单个数据类型元素。而列表可以包含任意数据类型的元素。

self是什么

slef是类的实例或者对象,在python中,self包含在第一个参数中

Python多个线程能用多个cpu吗?

Python的多线程不能利用多核cpu;原因是Python解释器使用了GIL锁,在任意时刻内只允许**单个python进程**。无论系统有多少个CPU核心,python程序都只能在一个CPU上运行。

Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

GIL锁和互斥锁

GIL锁保证同一个时刻只有一个线程能够拿到CPU;

互斥锁:多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱

首先假设只有一个进程,这个进程中有两个线程 Thread1,Thread2, 要修改共享的数据date, 并且有互斥锁

执行以下步骤

(1)多线程运行,假设Thread1获得GIL可以使用cpu,这时Thread1获得 互斥锁lock,Thread1可以改date数据(但并
没有开始修改数据)

(2)Thread1线程在修改date数据前发生了 i/o操作 或者 ticks计数满100 (注意就是没有运行到修改data数据),这个
时候 Thread1 让出了Gil,Gil锁可以被竞争

(3) Thread1 和 Thread2 开始竞争 Gil (注意:如果Thread1是因为 i/o 阻塞 让出的Gil Thread2必定拿到Gil,如果
Thread1是因为ticks计数满100让出Gil 这个时候 Thread1 和 Thread2 公平竞争)

(4)假设 Thread2正好获得了GIL, 运行代码去修改共享数据date,由于Thread1有互斥锁lock,所以Thread2无法更改共享数据
date,这时Thread2让出Gil锁 , GIL锁再次发生竞争

(5)假设Thread1又抢到GIL,由于其有互斥锁Lock所以其可以继续修改共享数据data,当Thread1修改完数据释放互斥锁lock,
Thread2在获得GIL与lock后才可对data进行修改

以上描述了 互斥锁和Gil锁的 一个关系

return和yield的区别

共同点:都用来返回值,在一次性返回所有值的场景两者一样

区别:如果要返回的数据是通过for等循环生成的迭代器类型数据(如列表、元组),return只能在循环外部一次性地返回,yeild则可以在循环内部逐个元素返回

init、new、call的区别

构造函数:创建对象+初始化对象=new+init

    new方法是在实例创建之前被调用,是一个静态方法,主要功能就是创建一个类的实例并返回
    init方法是在实例创建之后被调用,主要功能是设置实例的一些属性的初始值
    new在init之前被调用,返回值传给init的第一个参数(self),然后init给这个实例设置参数
    call使实例能够像一个函数一样被调用,同时不影响实例本身的生命周期,但可以改变内部变量的值

=============================================
1、List(列表)和tuples(元组)的区别
列表 元组
可变的,可以被编辑 不可变,所以可以用作字典key
比元组慢 比列表快(因为支持的操作少)
list=[10,‘C’,20] tuple_1=(10,‘C’,20)
一般表示数据 一般表示结构

2、数组与列表的区别

    具有相同的存储数据方式,但是数组只能包含单个数据类型元素。而列表可以包含任意数据类型的元素。

3、python能编写脚本,一般认为是通用编程语言

    在运行前不需要编译,因此是一种解释性语言

4、lambda函数

    匿名函数,该函数可以包含任意数量的参数,但只能有一个执行操作的语句

    例:a=lambda x,y,z:x+y+z

5、self是什么

    self是类的实例或者对象,在python中,self包含在第一个参数中

6、[::-1]

    表示反转数组或者序列的顺序

7、如何随机化列表中的元素

    使用shuffle函数

8、如何生成随机数

    import random

    random.random()  返回0-1范围内的浮点数

9、range和xrange的区别

    功能上相同,都提供了一种生成整数列表的方法。区别是range返回一个python列表对象。xrange返回一个xrange对象,其运行时不是一次性生成整个静态列表,有利于大数据量的使用。

10、help()和dir()

    前者用于显示文档字符串,还可以查看与模块、关键字、属性等相关的使用信息

    后者用于显示定义的符号

11、深拷贝与浅拷贝

    浅拷贝,拷贝父对象,不会拷贝对象内部的子对象

    深拷贝,完全拷贝父对象及其子对象

12、python执行多线程能用多个cpu吗

    不能。因为python只有一个GIL(全局解释器锁),运行时必须拿到这个锁才能执行,在遇到I/O操作时会释放这把锁

好处:避免大量操作,更安全

缺点:多核变单核,只能并发不能并行

注:同步锁,给进程或者线程添加锁,避免死锁的出现

   死锁,两个及以上进程或者线程争资源而相互等待

   循环锁,同一线程多次请求同一资源,必须等其次数用尽才能释放

13、垃圾回收机制

(1)python垃圾回收主要以引用计数为主,分代回收为辅。引用计数法就是每个对象维护一个ob_ref,用来记录当前对象被引用的次数,即追踪到底有多少引用指向对象,当指向该对象的引用计数器为0,就会被虚拟机销毁。

(2)标记-清除。针对循环引用的情况:孤岛或未使用,互质的对象,没外部引用。把所有活动对象打上标记,把没有标记的回收。主要用来处理一些容器对象。

(3)分代回收。根据对象存货时间划分为3个不同集合,垃圾收集频率随时间增加而减小。

14、生成器与迭代器

    生成器:一边循环一边计算的机制。为了使用海量数据却不占用大量内存。通过在函数中调用yield形式创建。是一种特殊的迭代器,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。

    迭代器:对象要求支持迭代器协议,即两个方法 __iter__() 与 __next__()

15、装饰器

    @+函数名修饰,通过装饰器函数,在不修饰原函数的前提下,来对函数功能进行合理扩充

    可以用于参数检查、统计时间、缓存等

16、return和yield的区别

共同点:都用来返回值,在一次性返回所有值的场景两者一样

区别:如果要返回的数据是通过for等循环生成的迭代器类型数据(如列表、元组),return只能在循环外部一次性地返回,yeild则可以在循环内部逐个元素返回

17、set和字典的区别

    set和字典相比在于没有存储对应的value,set的原理和dict一致,无法放入可变对象

18、init、new、call的区别

    构造函数:创建对象+初始化对象=new+init

    new方法是在实例创建之前被调用,是一个静态方法,主要功能就是创建一个类的实例并返回

    init方法是在实例创建之后被调用,主要功能是设置实例的一些属性的初始值

    new在init之前被调用,返回值传给init的第一个参数(self),然后init给这个实例设置参数

    call使实例能够像一个函数一样被调用,同时不影响实例本身的生命周期,但可以改变内部变量的值

19、内存管理机制

    引入机制、垃圾回收、内存池机制

20、实例方法、类方法、静态方法

    实例方法:第一个参数必须是实例对象,只能由实例对象调用

    类方法:使用装饰器@class method。第一个参数必须是当前类对象,参数名一般为cls,通过它来传递类的属性和方法(不能传实例的属性和方法),实例和类对象都可调用

    静态方法,使用装饰器@staticmethod,参数随意,但是方法中不能使用类或实例的任何属性和方法。

21、传参还是传址

    python的变量内存模型不同于C++,为每个对象分配内存空间

    将类型分为了可变类型:列表、字典

                           不可变类型:int,float,string ,tuple

    在参数传递时,实参将标签复制给形参,形参、实参指向同一对象。

    在函数内修改形参,对不可变类型,修改变量创建一个新对象,形参标签转给新对象,实参无变化。

    采用传对象引用的方法,可变对象类似于传址,不可变对象相当于传值

22、is和==的区别

    is是判引用地址是否相同,==是判值相同

23、import机制

    所有加载到内存的模块都放在sys.modules,当import一个模块时首先会在这个列表中查找是否已经加载了此模块,如果加载了只是将模块的名称加入到正在调用import模块的local名字空间中

    一个模块不会重复载入

顺序嵌套 本模块 import A Aimport B

            本模块只能调用A,无法用B,各个模块的local名字空间是独立的

循环嵌套

(1)from 文件夹 import 模块名 只适用于父目录调用子目录

(2)import sys

    sys.path.append(’绝对路径‘)

    import 模块名

24、如何提高python的运行效率

    使用生成器;关键代码使用外部功能包(Cython,pylnlne,pypy,pyrex);针对循环的优化--尽量避免在循环中访问变量的属性

以上内容均来源于各个版主、牛客网总结

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值