一、语言特性
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);针对循环的优化--尽量避免在循环中访问变量的属性
以上内容均来源于各个版主、牛客网总结