-
线性结构:list/tuple,array/collections.namedtuple
-
链式结构:-----------,collections.deque(双端队列)-
-
字典结构:dict,collections.Counter/OrderedDict
-
集合结构:set/frozenset,-----------
-
排序算法:sorted,----------
-
二分算法:-----------,bisect
-
堆算法:--------,heapq
-
缓存算法:-----------,functools.lru_cache(左边代表内置,右边代表第三方)
内置结构常用方法
python内置数据类型注意点:
-
元组不可变指的是保存的数据引用不可变,比如列表套元组,列表可以改变
-
字典底层是hash表实现,复杂度是O(1)
python内存管理
-
引用计数:引用数为0时,清除
-
标记清除,是解决循环引用,从根对象可以到达的每个对象,不可达到的就清除
-
分代回收:对象生命周期分为0,1,2代 ,每隔一段时间对从第代开始进行标记清除
python常用标准库?
-
综合:re,json,pickle,math,hmac,hashlib,random,logging,pytest
-
异步编程:threading,multiprocessing,gevent,asyncio
-
网络:urllib,socket,http,aiohttp,request
-
文件,系统:os,sys,io
-
函数式编程:itertools,functools
第三方库?
- flask,django,sqlalchemy,celery,pymysql,pymongo,redis,request,xlrd,xlwt,lxml,appium,selenium,scrapy。。
GIL(全局解释器锁)
-
是由于cpython解释器造成的
-
每个线程在执行过程中都需要先获取GIL,保证同一时刻只有一个线程执行代码
-
什么情况会释放锁:在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL
深浅拷贝
-
深拷贝(copy.deepcopy):对于一个对象递归拷贝,只有所有嵌套层全为不可变数据类型才指向,否则一律拷贝
-
浅拷贝:对于可变数据类型,顶层拷贝,内部指向;对于不可变数据类型,全部指向;切片和赋值工厂函数都属于浅拷贝
with打开文件的时候帮我们做了什么?
-
with是一种上下文管理协议,帮我们实现了try,except,finally和资源释放的代码,简化处理流程
-
上下文管理器就是实现来enter和exit两个魔法方法的对象都可以叫上下文管理器,还可以用contextlib中的contextmanager来实现
-
from contextlib import contextmanager @contextmanager def my_open(path, mode): f = open(path, mode) yield f f.close()
os模块常用方法?
sys模块常用方法?
python解释器种类以及相关特点?
-
cpython(默认),ipython(基于cpython,交互式),jpython(将python代码解释称java字节码),ironpython(将python代码解释为.net)
什么是PEP8?
-
命名
-
常量:大写加下划线 USER_CONSTANT。
-
私有变量或函数名 : 小写和一个前导下划线 _private_value
-
内置变量 : 小写,两个前导下划线和两个后置下划线 class
-
-
不要乱用*args和**kwargs
-
一行不要太长,一个函数不要超过30行,一个类不要超过200行,一个模块不要超过500行
python之禅
优美胜于丑陋(Python 以编写优美的代码为目标)
明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)
简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)
复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)
扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)
间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)
可读性很重要(优美的代码是可读的)。。。
了解docstring吗?
-
DocStrings 文档字符串是一个重要工具,用于解释文档程序,帮助你的程序文档更加简单易懂。
我们可以在函数体的第一行使用一对三个单引号 ''' 或者一对三个双引号 """ 来定义文档字符串。
你可以使用 doc(注意双下划线)调用函数中的文档字符串属性。(https://www.runoob.com/w3cnote/python-docstrings.html)
了解类型注解吗?
-
函数参数指定类型,比如
-
def add(x:int,y:int)->int: pass
-
python命名规范?更多规范可以参考(https://www.cnblogs.com/kilometerwine/p/9650154.html)
-
由数字字母下划线组成
-
不能以数字开头,最好别以下划线开头(因为有可能和关键字重复)
python代码规范工具:
-
Black和Pylint(https://www.jianshu.com/p/7f987475394a)
简述 any()和 all()方法
-
any():只要迭代器中有一个元素为真就为真
-
all():迭代器中所有的判断项返回都是真,结果才为真
当退出 Python 时是否释放所有内存分配?
-
那些具有对象循环引用或者全局命名空间引用的变量,在 Python 退出是往往不会被释放 另外不会释放 C 库保留的部分内容(https://blog.csdn.net/weixin_42976139/article/details/101469367)
pathlib 的用法举例
dir()是干什么用的?
-
dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法dir(),该方法将被调用。如果参数不包含dir(),该方法将最大限度地收集参数信息。(https://www.runoob.com/python/python-func-dir.html)
断言什么时候用?
-
防御性的编程
-
运行时对程序逻辑的检测
-
合约性检查(比如前置条件,后置条件)
-
程序中的常量
-
检查文档
私有化
-
xx: 公有变量
-
_x: 单前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问
-
__xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)
-
xx:双前后下划线,用户名字空间的魔法对象或属性。例如:
__init__
, __ 不要自己发明这样的名字 -
xx_:单后置下划线,用于避免与Python关键词的冲突
-
通过name mangling(名字重整(目的就是以防子类意外重写基类的方法或者属性)如:_Class__object)机制就可以访问private了
怎样一次声明多个变量并赋值
#给多个变量赋值 data=['alex',84,[1900,3,38]] name,age,birth=data print(name) print(age) print(birth) ========== msg='hello' a,b,c,d,e=msg print(a,b,c,d,e) ========== msg='hello' a,_,_,_,b=msg print(a) print(b) #只给第一个和最后一个变量赋值 a,*_,b=msg print(a,b)
sorted和sort区别?
-
sorted对所有可迭代对象排序,sort知识list特有方法
-
前者会返回新列表,后者对原来列表操作
python中逻辑运算符,位运算符,赋值运算符?
python中使用多进制数字?
定义函数参数顺序?
-
位置参数,可变参数,默认参数,关键词参数
匿名函数?
-
定义 lambda 形参:返回值
-
定义并调用:(lambda 形参:返回值)(实参)
-
应用场景:比如用于map,reduce函数中
python函数怎么传参?
-
共享传参(看起来是可变参数引用传递,不可变参数值传递):实际上是共享传参,就是函数形参获得实参各个副本的引用
-
默认参数为可变参数时,只计算一次
函数递归调用停止条件?
-
默认为1000,可以调整
-
或者设置递归条件停止
map,reduce,filter函数
functools模块
函数装饰器有什么作用?请列举说明?
可以无侵入式的为程序添加功能
import time def time_fun(fun): def wrapper(): start = time.time() fun() end = time.time() take = end - start return take return wrapper @time_fun def fun1(): for i in range(10000000): pass
魔法方法
metaclass 作用?以及应用场景?
python中的组合和继承
- 组合是通过对现有对象进行拼装即组合产生新的具有更复杂的功能,通俗理解为把一个类的实例放到另一个类叫组合,一般优先使用组合,组合不关心局部类的实现,只关心局部类有没有什么功能或者属性,拿来用,属于黑盒式复用
- 继承属于白盒式复用,优点在于可以很方便的修改被复用的代码
#组合
class A: def __init__(self, a, b): self.a = a self.b = b class B(A): def __init__(self, a, b): self.c = A(a, b) b1 = B(1, 2) print(b1.c) == > A的对象
多继承及MRO(非重点)
-
-
但在多继承上有区别,super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,具体看前面的输出结果
-
多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错
-
单继承时,使用super方法,则不能全部传递,只能传父类方法所需的参数,否则会报错
-
多继承时,相对于使用类名.init
property
class Goods: @property def price(self): print('@property') @price.setter def price(self, value): print('@price.setter') @price.deleter def price(self): print('@price.deleter') obj = Goods() obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数 del obj.price # 自动执行 @price.deleter 修饰的 price 方法
鸭子类型或者多态
- 同一父类同一属性或者方法的表现不同,比如黑人白人都是人,都有皮肤,但是皮肤颜色不同,他们都会唱歌,但可能黑人唱歌天赋好一点
pymysql的基本使用
from pymysql import * def main(): find_name = input("请输入物品名称:") # 创建Connection连接 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='jing_dong', charset='utf8') # 获得Cursor对象 cs1 = conn.cursor() # 非安全的方式 # 输入 " or 1=1 or " (双引号也要输入) # sql = 'select * from goods where name="" or 1=1 or ""' % find_name # 安全的方式,构造参数列表 params = [find_name] count = cs1.execute('select * from goods where name=%s', params) # 注意: # 如果要是有多个参数,需要进行参数化 # 那么params = [数值1, 数值2....],此时sql语句中有多个%s即可 # 打印受影响的行数 print(count) # 获取查询的结果 # result = cs1.fetchone() result = cs1.fetchall() # 打印查询的结果 print(result) # 关闭Cursor对象 cs1.close() # 关闭Connection对象 conn.close() if __name__ == '__main__': main()
pymongo的基本使用
# 导入pymongo并选择要操作的集合 数据库和集合乜有会自动创建 from pymongo import MongoClient client = MongoClient(host, port) collection = client[db名][集合名] 添加一条数据 ret = collection.insert_one({"name": "test10010", "age": 33}) 添加多条数据 t = collection.insert_many(item_list) 查找一条数据 t = collection.find_one({"name": "test10005"}) 查找全部数据 结果是一个Cursor游标对象,是一个可迭代对象,可以类似读文件的指针,但是只能够进行一次读取 # find返回所有满足条件的结果,如果条件为空,则返回数据库的所有 t = collection.find({"name": "test10005"}) # 结果是一个Cursor游标对象,是一个可迭代对象,可以类似读文件的指针, for i in t: print(i) for i in t: # 此时t中没有内容 print(i)
redis的基本使用
from redis import * sr = StrictRedis(host='localhost', port=6379, db=0) # 简写 # sr=StrictRedis() # 添加键name,值为ycg result = sr.set('name', 'ycg') # 输出响应结果,如果添加成功则返回True,否则返回False print(result)
zip函数的用法
-
zip()函数在运算时,会以一个或多个序列(可迭代对象)做为参数,返回一个元组的列表。同时将这些序列中并排的元素配对。
format函数用法
python中except用法?
#第一种 try: xxx except: xxx #第二种 try: xxx except xxError: xxx #第三种 try: xxx except xxError1,xxError2,xxError3: xxx #第四种 try: xxx except xxError,args(参数): xxx(可以用到args) #第五种 try: xxx except xxError: xxx except xxError: xxx except xxError: xxx #完整格式是 try: 可能引发异常现象的代码 except: 出现异常现象的处理代码 else: 未出现异常现象的处理代码 finally: try代码块结束后运行的代码(一定执行)
random
-
random.random():生成一个 0-1 之间的随机浮点数;
-
random.uniform(a, b):生成[a,b]之间的浮点数;
-
random.randint(a, b):生成[a,b]之间的整数;
-
random.randrange(a, b, step):比如(1,10,2)就是从1,3,5,7,9取随机;
-
random.choice(sequence):从特定序列中随机取一个元素,这里的序列可以是字符串,列表, 元组等
-
random.shuffle(序列):打乱一个序列
time模块:
datetime模块:
-
主要分为time类,date类,datetime类(前两者结合),timdelta(时间差),tzinfo(时区信息)
-
strftime(从时间转换为字符串),strptime,更多可见:https://www.cnblogs.com/awakenedy/articles/9182036.html
python logging模块详解:
python中metaclass使用举例
猴子补丁
-
即在运行时对方法 / 类 / 属性 / 功能进行修改,把新的代码作为解决方案代替原有的程序,也就是为其打上补丁。
-
使用猴子补丁的方式,gevent能够修改标准库里面大部分的阻塞式系统调用,包括socket、ssl、threading和 select等模块,而变为协作式运行。也就是通过猴子补丁的monkey.patch_xxx()来将python标准库中模块或函数改成gevent中的响应的具有协程的协作式对象。这样在不改变原有代码的情况下,将应用的阻塞式方法,变成协程式的。
python中常见异常
-
AttributeError,OSError,IOError,ImportError,SyntaxError,TypeError,NameError
python中的接口如何实现
-
接口只是定义了一些方法,而没有去实现,多用于程序设计时,只是设计需要有什么样的功能,但是并没有实现任何功能,这些功能需要被另一个类(B)继承后,由 类B去实现其中的某个功能或全部功能。
在python中接口由抽象类和抽象方法去实现,接口是不能被实例化的,只能被别的类继承去实现相应的功能。
个人觉得接口在python中并没有那么重要,因为如果要继承接口,需要把其中的每个方法全部实现,否则会报编译错误,还不如直接定义一个class,其中的方法实现全部为pass,让子类重写这些函数。
当然如果有强制要求,必须所有的实现类都必须按照接口中的定义写的话,就必须要用接口。更多参考:https://blog.csdn.net/kobeyan/article/details/44344087
python中的反射(又叫自省)
-
反射,reflection,指的是运行时获取类型定义信息。 一个对象能够在运行时,像照镜子一样,反射出其类型信息。简单说,在Python中,能够通过一个对象,找出其type、class、attribute或method的能力,称为反射或自省。 具有反射能力的函数有type(),isinstance(),callable(),dir(),getattr()等
怎么理解restful风格
-
restful风格是一种接口开发的风格,中文翻译就是表现层状态转换,表现层要表现的就是资源,比如html,xml,json,http请求中主要体现在accept和content-type两个请求头字段,状态转换就是客户端和服务端交互的过程中数据和状态肯定会发生改变
-
总结就是,每一个url代表一种资源;客户端和服务端之间,传递着这种资源的表现层;客户端通过http四个动词对服务端资源操作,来实现资源的状态转换
pycharm中的Mark as root 和sys.path.append(xxx)效果一样,都是讲非python包(就是没有init文件)加入python解释器搜寻路径
str和repr
-
其实二者差不多,大多数情况,都是用来自定义在打印类对象的时候输出的内容,但django查询集中,优先使用repr
python几种数据结构底层实现:
-
list被实现为:对其它对象的引用组成的连续数组
-
tuple被实现为:空间大小一定,元素地址一定的连续数组,更多可见:http://c.biancheng.net/view/5360.html
-
dict被实现为:伪随机探测(pseudo-random probing)的散列表(hash table),由于这个实现细节,只有可哈希的对象(不可变数据类型)才能作为字典的键。
-
set被实现为:没有值的字典,实际上也是hash表,set是可变的,但是其值不可变。更多关于hash表的内容可见 :https://www.cnblogs.com/ycg-blog/p/12704785.html
-
更多可见:https://blog.csdn.net/siyue0211/article/details/80560783
python有了GIL为什么还要线程锁
-
GIL是限制同一个进程中只有一个线程进入Python解释器。而线程锁是由于在线程进行数据操作时保证数据操作的安全性(同一个进程中线程之间可以共用信息,如果同时对数据进版行操作,则会出现公共数据错误)其实线程锁完全可以替代GIL,但是Python的后续功能模块都是加在GIL基础上的,所以无法更改或去掉GIL,这就是Python语言最大的bug…只能用多进程或协程改善,或者直接用其他语言写这部分
python单例应用场景:
-
日志logger插入,计时器、权限校验、网站计数器,windows资源管理器,回收站,线程池,数据库连接池等资源池(https://www.cnblogs.com/kaiping23/p/9622855.html)
如何判断一个对象是函数还是方法
-
types模块里面有Functiontype和Methodtype,用instance判断
python常用模块总结:
python操作excel:
pyechart在django中显示:
python中的nolocal:
-
nolocal用在闭包中,提升外部函数变量,使闭包函数可以修改外部函数中的变量,当知识读取变量,或者修改外部可变数据类型变量的时候nolocal可以省略
python pickle cpickle:
-
json模块是序列化和反序列化字符串,pickle是序列化为二进制,cpickle比pickle更快
python内存管理:
python闭包及陷阱:
单例及其实际应用场景:
sys.path维护的是python解释器的导包路径列表,加入其中的路径,都可以直接直接引用(就好像全局变量一样)
python Merry(异常处理模块,业务逻辑和异常处理分离):
argparse模块的使用:
python中的exec()、eval()以及complie():
re.compile:
占位符详解:
format详解:
python实用编程技巧:
python程序提高性能的20 种方法:
python获取命令行输出结果:
python中 r'', b'', u'', f'' 的含义:
python定义函数时,指定要传入参数的数据类型:
str(),repr(),eval():
python基础大整合:
Unicode与utf-8:
匹配中文的正则:
程序中出现中文导致, SyntaxError: Non-UTF-8 code starting with 'xc1',在第一行加上#coding=gbk,详情可见:
python3 Unicode编码字符串 转成汉字(u 开头 ):
a = "u5317u4eacu5e02" print(a.encode().decode())
pip的使用
-
pip命令:
a = [i if i % 2 is 0 else 0 for i in range(5)]#if写在前面一定要加else,可以理解为没有加else的话,相当于没有拿着一个变量去列表推导式找值 b = [j for j in range(5) if j % 2 is 0]
python进制转换
# 其他进制转换为十进制 # 二进制转换为十进制 a = int('10', 2) ==>2 # 八进制转换为十进制 b = int('10', 8) ==>8 # 十进制转换为其他进制 c = bin(10) ==>0b1010 d = oct(10) ==>0o12 e = hex(10) ==>0xa
json序列化时,可以处理的数据类型有哪些?如何定制支持datetime类型
自定义时间序列化转换器 import json from json import JSONEncoder from datetime import datetime class ComplexEncoder(JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.strftime('%Y-%m-%d %H:%M:%S') else: return super(ComplexEncoder,self).default(obj) d = { 'name':'alex','data':datetime.now()} print(json.dumps(d,cls=ComplexEncoder)) # {"name": "alex", "data": "2018-05-18 19:52:05"}
json序列化时遇到中文会默认转换成unicode ,如何让他保留中文形式
import json a=json.dumps({"ddf":"你好"},ensure_ascii=False) print(a) #{"ddf": "你好"}
asyncio的基本使用
yield和yield from的区别:
def fun1(x): yield x def fun2(x): yield from x a = [1, 2, 3, 4, 5] for i in fun1(a): print(i) # 结果:[1, 2, 3, 4, 5] for j in fun2(a): print(j) # 结果:1,2,3,4,5 # 区别:yield和yield from后边加上可迭代对象的时候,yield from是将可迭代对象中的元素一个一个yield出来,而yield是直接yield的是可迭代对象
functools.partial
functools模块用于高阶函数:作用于或返回其他函数的函数。一般而言,任何可调用对象都可以作为本模块用途的函数来处理。
functools.partial返回的是一个可调用的partial对象,使用方法是partial(func,*args,**kw),func是必须要传入的,而且至少需要一个args或是kw参数。
from functools import partial def add(a, b, c): return a + b + c p = partial(add, 12) x = p(2, 3) print(x) # 17
asyncio基本使用
python 装饰器
#最基本的装饰器
def hint(func): def wrapper(*args, **kwargs): print('{} is running'.format(func.__name__)) return func(*args, **kwargs) return wrapper @hint def hello(): print("Hello!") >>> hello.__name__ 'wrapper' ##函数名字已改变 #想要函数名不变: from functools import wraps def hint(func): @wraps(func) def wrapper(*args, **kwargs): print('{} is running'.format(func.__name__)) return func(*args, **kwargs) return wrapper @hint def hello(): print("Hello!") #装饰器带参数 from functools import wraps def hint(coder): def wrapper(func): @wraps(func) def inner_wrapper(*args, **kwargs): print('{} is running'.format(func.__name__)) print('Coder: {}'.format(coder)) return func(*args, **kwargs) return inner_wrapper return wrapper @hint(coder="John") def hello(): print("Hello!")
python什么时候用类方法,什么时候用静态方法,什么时候用实例方法
- 静态方法就是没有用到类里面的属性和方法的时候,可以用静态方法,主要是为了保证类的完备性
- 类方法是定义在类中,不属于某个具体对象的行为,被所有对象共同使用的行为,类方法里面不能使用实例变量和方法
python元类
python sort和sorted
- python sort 和python sorted的区别?
- python sort是在原对象上排序,而sorted会生成新的排序对象
- sorted和的实现原理都是基于timesort
-
Timsort是结合了合并排序(merge sort)和插入排序(insertion sort)而得出的排序算法,排序的输入的单位不是一个个单独的数字,而是一个个的块-分区。其中每一个分区叫一个run。针对这些 run 序列,每次拿一个 run 出来按规则进行合并。每次合并会将两个 run合并成一个 run。合并的结果保存到栈中。合并直到消耗掉所有的 run,这时将栈上剩余的 run合并到只剩一个 run 为止。这时这个仅剩的 run 便是排好序的结果。
-
综上述过程,Timsort算法的过程包括
(0)如何数组长度小于某个值,直接用二分插入排序算法
(1)找到最小run;优化run的大小;通过归并排序合并run
- 更多可见:https://blog.csdn.net/yangzhongblog/article/details/8184707
-
- sort的实现原理
- python内部的sort采用的是混合(hybrid)排序,规模小的时候采用 binary insertion,规模大的时候采用 sample sort
python互斥锁(lock),可重入锁(rlock,同一线程可以多次获取锁),死锁:
- 常规锁和Python中的Rlock之间的一个区别是,常规锁可以由不同的线程释放,而重入锁必须由获取它的同一个线程释放,同时要求解锁次数应与加锁次数相同,才能用于另一个线程。
- 产生死锁的条件:“迭代调用”死锁,互相调用死锁,更多可见:https://www.jb51.net/article/74426.htm
进程和线程之间的通信方式
进程
- 管道(匿名管道):半双工的通信方式,数据只能单向流动,且只能在有亲缘关系(父子进程或兄弟进程)的进程间使用;
- 命名管道:FIFO,半双工的通信方式,但允许在无亲缘关系的进程间通信;
- 消息队列:消息的链表,存放在内核中,并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点;
- 共享内存:映射一段能被其他进程访问的内存,这段内存由一个进程创建,但多个进程都可以访问;
- 信号:信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生.
- 信号量:是一个计数器,用于控制多个进程间对共享资源的访问;
- socket
线程
-
锁机制:包括互斥锁、条件变量、读写锁
- 互斥锁提供了以排他方式防止数据结构被并发修改的方法。
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
- 互斥锁提供了以排他方式防止数据结构被并发修改的方法。
- 信号量机制(Semaphore):包括无名线程信号量和命名线程信号量
- 信号机制(Signal):类似进程间的信号处理
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。