首页 > 编程语言 >面试题——python后端开发

面试题——python后端开发

时间:2023-05-04 18:47:00浏览次数:47  
标签:__ 面试题 请求 后端 python 对象 线程 数据 函数

Python 和 Java、PHP、C、C#、C++等其他语言的对比?

python语言,是面向对象、直译式计算机程序设计语言,python语法简洁清晰,具有丰富和强大的类库。
Python是完全面向对象的语言。函数、模块、数字、字符串都是对象。并且完全支持继承、重载、派生、多继承,有益于增强源代码的复用性
java是一种可以撰写跨平台应用软件的面向对象的程序设计语言.
PHP是一种通用开源脚本语言。
C语言,它既有高级语言的特点,又具有汇编语言的特点,它是结构式语言。
C++是C语言的继承,它既可以进行C语言的过程化程序设计,又可以进行以抽象数据类型为特点的基于对象的程序设计,还可以进行以继承和多态为特点的面向对象的程序设计。
C#语言,C#是微软公司发布的一种面向对象的

简述解释型和编译型编程语言?

编译型(需要编译器,相当于用谷歌翻译):编译型语言执行速度快,不依赖语言环境运行,跨平台差.
解释型(需要解释器,相当于同声传译):解释型跨平台好,一份代码,到处使用,缺点是执行速度慢,依赖解释器运行

8bit=1bytes

PEP8规范

使用空格来表示缩进,不要用tab
和语法相关每层缩进都要用4个空格
每行字符数不超过79
文件中函数与类用两个空格隔开
在同一类中函数,各方法之间一个空行隔开用

GC机制(垃圾回收机制)

一般高级语言为了保证内存的使用效率,都会有垃圾回收机制。
python的垃圾回收机制通过三种方式来做的:引用计数,标记清除,和分代回收。
引用计数是有多少变量指向它,他的引用计数就是几,没用变量指向它,他的内存就会被回收掉。但他会出现循环引入的问题。
标记清除就是为了解决引入计数存在的循环引入的问题。
-首先是标记阶段,他会把所有的活动对象打上标记,然后把那些没有标记的对象进行回收。
-然后他会循环引入的内存空间打上标记然后回收掉。
分代回收python把对象分为三代:
一开始,对象在创建的时候放在一代中,如果在一次一代的垃圾回收检查中,该对象存活下来,就会放到第二代中,同理在第二代的垃圾检查中,对象存活下来就会放在第三代,后面优先检查第一代中的对象,优先回收,其次一次往上做检查回收。

装饰器、生成器、迭代器

装饰器:在不改变被装饰函数的代码情况下给被装饰函数或程序添加新的功能.把函数或类作为参数,返回一个新的函数或类。
加载顺序自下而上,执行顺序自上而下。
迭代器:在类中定义了__iter__和__next__方法,__iter__方法返回了对象本身,__next__方法,返回下一组数据没有就会抛出异常。
生成器:使用了 yield 的函数被称为生成器。调用生成器函数时,会返回一个生成器对象。
有__iter__方法,且返回一个迭代器对象就是可迭代对象
有__next__就是一个迭代器
可迭代对象包括 迭代器(生成器)、序列(字符串,列表、元组)、字典 
遍历完会出现Stopiteraction异常
装饰器有两大特性:
1能把被装饰的函数替换成其他函数.
2装饰器在加载模块时立即执行.

可以被for循环的对象就是可迭代对象
可以用isinstace(迭代器,iterator)判断是否迭代器
isinstace(可迭代对象,iterable)判断是否可迭代对象

isinstace()检查对象是否类的对象
issubclass()检查类是否super的派生类

class MyDicorator:
    def __init__(self,func):
    	self.func=func
    def __call__(self,*args,**kwargs):
        res=self.func(*args,**kwargs)
	    return res

闭包

闭包是当一个内嵌函数引用其外部作作用域的变量。
1必须有一个内嵌函数
2内嵌函数必须引用外部函数中的变量
3外部函数的返回值必须是内嵌函数

函数递归

在调用一个函数的内部又调用自己,所以递归的本质就是一个循环的过程,它的大前提就是递归调用一定要在某一层结束,如果不结束,会形成一个死循环.

python是值传递还是引用传递?

值传递:一个数据值可以被多个变量名绑定,将其中一个变量名当做参数传入函数中,原来的值以及其他指向这个值的变量名不会受到影响
引用传递:一个数据值可以被多个变量名绑定,将其中的一个变量名当做参数传入函数中,原来的值以及指向这个值的变量名都会受到影响
严格意义上来讲,python既不是值传递也不是引用传递,python有自己的传递方式,规则是:
如果传递的是不可变类型,在函数中修改,就不会影响原来的变量
如果传递的值是可变类型,在函数中修改、添加个别元素,会影响原来的变量。如果是重新复制,例如a=新的列表,那么就不会影响原来的变量
可变类型有:列表、集合、字典
不可变类型:数字,字符串,元组

python设计模式

设计模式是面对各种问题进行提炼和抽象而形成的解决方案(23种)
主要分为三大类: 创建类设计模式、结构类设计模式、行为类设计模式
创建类设计模式(5种):单例模式,工厂模式,建造者模式、原型模式
单例模式是指:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式的优点
1、由于单例模式要求在全局内只有一个实例,因而可以节省比较多的内存空间;
2、全局只有一个接入点,可以更好地进行数据同步控制,避免多重占用;
3、单例可长驻内存,减少系统开销。
结构类设计模式(7种):代理模式、装饰器模式、适配器模式、门面模式、组合模式、享元模式、桥梁模式
行为类设计模式(11种):策略模式、责任链模式、命令模式、中介者模式、模板模式、迭代器模式、访问者模式、观察者模式、解释器模式、备忘录模式、状态模式

魔法方法

__new__:是在实例创建之前被调用的,用于创建实例,然后返回该实例对象,是个静态方法。
__init__:是当实例对象创建完成后被调用的,用于初始化一个类实例,是个实例方法。
__str__:对象被执行打印操作的时候自动触发
__call__:对象加括号调用的时候自动触发
__getattr__:对象. 不存在的名字的时候自动触发
__getattribute__:对象. 名字会自动触发,有它的存在就不会执行__getattr__
__setattr__:给对象添加或修改数据的时候自动触发
__delattr__:删除属性的时候会触发   
__enter__:当对象被当作with上下文管理操作的开始自动触发,并且该方法返回as后面的变量名就会接收到什么
__exit__:with上下文管理语法运行完毕之后自动触发(子代码结束)

__new__和__init__区别:
1. __new__是构造方法,__init__是初始化函数。
2.__new__通常不需要手动定义,一般在元类编程中使用,控制类的生成过程。
3.__new__第一个被执行,然后执行__init__绑定实例变量。
4.__new__必须有返回值,返回值是该类的实例,它会被__init__函数接收,通常叫做self变量

如何自定制上下文管理器?

一个对象如果实现了__enter__和__exit__方法,那么这个对象就支持上下文管理协议,及with语句。
上下文管理协议适用于那些进入和退出之后自动执行一些代码的场景,比如文件、网络连接、数据库连接或使用锁,s使用事务的编码场景等。比如当我们使用sqlarchemy时,将session.commit()和session.close()写在__exit__中。
使用:
class ComonSession:
    def __enter__(self):
        print('进入with语句块时执行此方法,此方法如果有返回值会赋值给as声明的变量')
        self.session=session
        return self.session
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.session.close()
with ComonSession() as session:
    session.filter()
print('上下文管理器结束了')

反射

利用字符串操作对象的数据和方法
1.hasattr()判断对象是否含有某个字符串对应的属性名或方法名
2.getattr()根据字符串获取对象对应的属性名(值)或方法名(函数体代码)
3.setattr()根据字符串给对象设置或者修改数据
4.delattr()根据字符串删除对象里面的名字

接口

接口泛指实体把自己提供给外界的一种抽象化物(可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被内部修改而不影响外界其他实体与其交互的方式.
接口就是规范只需要知道接口,按照这个接口做你具体做的事情,就可以融合到整个系统中了。
在项目中接口在项目就是一个业务逻辑,面向接口编程就是先把客户的业务提取出来
常见的接口一种是http接口,一种只web service接口
http接口就是get,POST,PUT,DELETE
-get和post区别
1方式get参数直接放到了url里面,post是把参数放到了表单里面
2get长度有限2M左右post没有大小限制
3get参数放到浏览器中不安全,post在表单中会稍对安全

oop编程(面向对象编程)

面向对象编程有三大特征:封装,继承,多态
封装:把一堆数据属性与方法数据放在一个容器中,这个容器就是对象。让对象可以通过 "." 来调用对象中的数据属性与方法属性。
继承:是子类可以继承父类的数据属性与方法属性,并可以对其进行修改或使用。
多态:指的是一类事物有多种形态,一个抽象类有多个子类,不同的子类对象调用相同的方法,产生不同的执行结果,多态可以增加代码的灵活度

鸭子类型:python面向对象中描述接口的一个概念,区分与其他编程语言,
python不需要显示的继承一个接口(类),只要类中有对应的属性跟方法,我们就称这几个类的对象为同一种类型。

猴子补丁:在程序运行过程中,动态替换的一种技术
比如在python2中的mysqldb到python3中无法兼容,这时候就可以用pymysql.install_as_mysqlDB()动态替换
或者在使用gevent动态替换会阻塞的代码,gevent执行猴子补丁会执行代码:monkey.patch_all()同步的代码遇到io操作会阻塞并且释放gil锁,这条线程就会释放cpu的执行。中的猴子补丁执行monkey.patch_all()就会执行猴子补丁。动态将所有的同步代码替换成异步代码,异步代码遇到io不会释放gil锁。time模块和socket模块都会阻塞,执行monkey.patch_all()之后time模块和socket模块已经是包装之后的,不再是原来的了。
抽象类就是对一堆类共同内容的抽取,包括:属性和方法。

python当中如何理解一切皆对象?

(1)对象是由类产生的,也就是说每一个对象都有产生其的类,所以我们可以通过print(type(数据))来查询该对象的父类
(2)对象可以使用类当中的属性。所以Python当中的数据类型有很多内置方法,这些内置方法其实就是类当中的一些方法
(3)我们自己定义的类,它的父类默认是type,说明我们自己定义的类也是一个对象
(4)很多数据的父类都是type,type是Python中内置的元类,我们继续print(type(type)),结果依然是type,也可以理解为type也是type的一个对象

python中的type和object有什么关系?

首先查看一个类的父类,可以用双下bases,查找一个类由什么实例化而来,用双下class
1.可见任何类都是由type实例化得来
然后我们再用这两个方法测试type:
print(type.__class__)  # <class 'type'>
print(type.__base__)  # <class 'object'>
2type是由type本身实例化而来的,而它的父类却是object
print(object.__class__)  # <class 'type'>
print(object.__base__)  # None
3object没有父类,它是类中最顶端的存在。但是object却是由type实例化得来的
可以的得到结论:
(1)所有类(包括object和type)都是由 type实例化得来的
(2)type的父类是object,object的无父类,object是类中最顶端的存在

继承原理 MRO方法

mro是方法解析顺序:每一个类都会有mro顺序,python会在MRO列表上从左往右一次开始查找基类,直到找到第一个匹配这个属性的类为止。
MRO列表会遵循如下三条准则
1、子类会先于父类被检查
2、多个父类会根据它们在列表中的顺序被检查
3、如果对下一个类存在两个合法的选择

super()代表父类的定义,而不是父类对象

绑定方法和非绑定方法

classmethods:绑定给类的方法,由类来调用,自动将类本身当作第一个参数传入
staticmethod:非绑定方法,不与类和对象绑定,类和对象都可以调用,普通函数,没有自动传值
property:一种特殊属性、访问它时会执行一段功能,用来绑定给对象的方法,将函数对象伪装成数据属性,然后返回值

反射、cbv源码简述

反射就是通过字符串的形式操作对象相关的属性.
hasattr 检测是否含有某属性
getattr 获取属性
setattr 设置属性
delattr 删除属性
CBV源码简述:
根据前端请求方式的不同自动匹配执行对应的方法-在url路由中的views.类 名.as_view()的源码下可以看到是被@classonlymethod修饰的类方法,内部定义闭包函数传参并返回闭包函数名、在dajong启动的时候会执行urls的as_view()产生变 形为views.view,在浏览器提交请求的时候就会触发view方法,通过view下的self 使用类的对象,返回self.dispatch属性、在父类中的dispathc函数通过反射机制就 通过字符串操作对象属性口只有在被完成后才会真正执行,就是可以事先写好逻辑接口,事后实现接口功能

类变量和实例变量的区别?

类变量中的对象是共有的,实例变量中的对象是私有的。如果一个对象点类名当中的属性修改之后,那么所有对象点这个属性都会拿到修改后的值。当实例的属性被修改后,改变的只有这个实例的值。

什么是接口幂等性问题,如何解决?

接口幂等性就是用户对同一操作发起一次请求或者多次请求的结果是一致的,不会因为多次点击而产生副作用,get请求幂等,put请求幂等,delete请求幂等,post请求不幂等。我们尤其在涉及数据库修改操作时需要注意保证接口的幂等性。首先,我们要知道什么场景下可能不幂等,在发送请求到收到响应的这一段时间,请求端不知道是否发送了请求,则可能多次的发送了请求,响应端也并没有对多次请求做校验,所以多次处理了相同的请求。
针对这一点,我们有三种方案保证接口的幂等:
方式一:唯一主键,unique,新增用户名或者手机号唯一,但是不能解决订单
方式二:token机制:
1.服务端首先需要提供获取token的接口。如果业务存在幂等的问题,就在执行业务之前(比如商城类项目,在进入支付页面时)访问接口,服务端将token保存在redis中,并且返回给前端一份
2.调用业务的接口(比如支付接口)请求时,携带token
3.服务端判断token是否存在redis中,存在表示第一次请求,然后删除redis中的token,执行业务
4.如果token不在redis中,就表示是重复操作,直接返回一个标记给前端,就可以避免接口重复执行
方式三:前端限制按钮只能点击一次

什么是GIL锁?有什么作用?

GIL锁全称全局解释器锁,本质就是一个大的互斥锁,这是Cpython的一种机制,只存在于cpython。作用就是限制多线程同时执行,使得在同一进程内任何时刻仅有一个线程在执行,它限制了一个线程只有获取了gil锁才能执行,没有锁就不能执行。某个线程运行完毕后会释放锁,其他线程才能运行。如果线程运行过程中遇到了io操作,则锁会解开,使其他线程运行。GIL只能确保同进程内多线程数据不会被垃圾回收机制乱删,并不能确保程序里的数据是否安全。
python垃圾回收机制需要有一条线程来做,如果同一时刻有多个线程正在执行,垃圾回收机制可能会把正在其他线程正在使用的变量给回收掉。
GIL锁的弊端:使用Cpython解释器时,GIL锁会使多线程的执行效率很低,无法充分利用CPU资源,基本等同于单线程执行。

python线程如何保证运行安全?

(1)使用互斥锁:即使有GIL锁的存在,也需要使用互斥锁,因为GIL锁只是保证正在执行的线程中的数据不被垃圾回收机制回收,并不能保证数据安全
from threading import Lock
(2)使用队列:
多个线程访问同一个资源,访问顺序不确定,可以使用队列来保证线程安全问题。多个线程可以通过put()和get()方法向队列中添加和获取元素
import queue
q = queue.Queue()
q.put(item)
item = q.get()
(3)使用信号量(Semaphore):信号量可以控制同时访问共享资源的线程数量,从而避免线程安全问题。

常用模块

基础os,sys,time,json,pickle,randon,hashlib,re,math,logging
爬虫requests,BeautifulSoup,xpath,gevent,asyncio,twisted
logging日志级别:debug、info、warning、error、critical
json是可以在不同语言之间交换数据,pickle只在python之间调用
json只能序列化最基本的数据类型,而pickle可以序列化所有的数据类型
requests:请求库
BeautifulSoup:解析库
selenium:自动化测试工具
pymysql:存储库。操作mysql数据库的
Scrapy是一个自动化测试工具,而爬虫中使用它主要是为了解决requests无法直接执行JavaScript代码的问题。

进程线程协程

进程是资源分配的最小单位,一个应用程序至少有一个进程。
线程是cpu调度的最小单位,一个进程下至少有一个线程。
协程:单线程下的并发,程序层面控制任务切换
进程的实现:
	1写一个类,继承Process,重写类的run方法,实例化得到对象,对象.start开启了进程
    2通过Process类实例化得到一个对象,传入任务 ,调用对象.start 开启了进程
from multiprocessing import Process
import time
def run(name):
	print('%s is running' % name)
	time.sleep(3)
	print('%s finished his run' % name)
if __name__ == '__main__':
	p = Process(target=run, args=('XWenXiang',))  # 创建一个进程对象
	p.start()  # 告诉操作系统创建一个新的进程
线程代码实现:
	1写一个类,继承Thread,重写类的run方法,实例化得到对象,对象.start开启了线程
    2通过Thread类实例化得到一个对象,传入任务,调用对象.start开启线程
协程实现:
	早期之前借助于gevent,基于greenlet写的。但是可以借助async(写在函数之前)和await关键字开启协程。

什么是IPC,进程间通信报的方式?

IPC就是指进程间通信
进程间通信有两种情况:同一台机器上两个进程通信,不同机器上两个进程通信
通信方式:
1.python queue可以做进程间通信
2.消息队列,可以使用redis(一个进程写进去,另一个进程拿出来)、rebbitmq、kafka
3.通过socket套接字,展现形式1:使用一个框架调用另一个框架的接口(例如我们 使用django框架写orm拿到mysql的数据,这就是通过套接字,一个进程从另一个进程中拿到数据)。展现形式2:RPC调用:远程过程调用(微服务使用较多)
from multiprocessing import Queue,Process
def write(q):
    for i in ["a", "b", "c", "d"]:
        q.put(i)

        print("put {0} to queue".format(i))
def read(q):
    while 1:
        result =q.get()
        print("get {0} from queue".format(result))
def main():
    q = Queue()
    pw = Process(target=write, args=(q,))  # 定义一个写的进程

    pr = Process(target=read, args=(q,))  # 定义一个读的进程
    pw.start()
    pw.join()
    pr.start()
    print(q)

if __name__ == '__main__':
    main()
'''
运行结果
put a to queue
put b to queue
put c to queue
put d to queue
<multiprocessing.queues.Queue object at 0x000002BF93EA7670>
get a from queue
get b from queue
get c from queue
get d from queue
'''

解释为什么计算密集型用多进程,io密集型用多线程?

计算密集型是指更多需要cpu参与的程序,io密集型是指阻塞态更多的程序。
由于GIL锁的存在,即使是多核机器,同一时刻也只能有一个线程在执行,线程需要cpu去调度执行。
如果是计算密集型,开启多线程不能利用多核优势(cpython中的多线程实际是由于单个线程在不同程序中来回切换产生的),开启多进程能利用多核优势。io操作不消耗cpu,并且多线程可以更快地在不同程序之间切换,开启多线程在一个时间段内可以产生并发效果

什么是并发、并行?

并发:同一时间段内,执行多个任务的能力
并行:同一时刻执行多个任务的能力,必须要多cpu执行

python如何实现并发?

多线程:使得某个线程的IO操作和另一个线程对的CPU计算可以同步执行,避免cpu等待,提高效率
多进程:multiprocess,利用cpu多核的特点,真正的并行的执行任务
异步IO:在单线程利用CPU和IO同时执行的原理,实现函数的异步执行
使用互斥锁对多个线程同时修改数据的操作加锁,保证数据安全
使用消息队列实现不同进程之间的数据通信
使用线程池、进程池管理线程、进程的数量,保证程序执行的效率

僵尸进程,孤儿进程

僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程
在回收僵尸进程之前, 如果父进程结束了,则僵尸进程变为孤儿进程,进而被init进程接管、回收

python数据量大时怎么优化?

1.使用列表生成式或者迭代器替代循环
2.python访问局部变量相较于全局变量消耗资源更少,效率更高,应当减少全局变量使用
3.在使用django的orm时可以利用惰性查询进行优化,使用defer和only减少数据库的压力
4.对于数据量大并且查询频率较高的数据量,可以使用缓存查询

什么是同步、异步?

同步异步是在程序调用的角度来看:
同步是指一件事一件事的做,只有执行完毕前一个任务,才会执行下一个任务
异步是指:当一个任务开始执行,无需等待该任务完成,就可以切换到另一个任务执行
同步意味着有序,异步意味着无序。
异步举例:例如我们在网页上下载一个文件,当我们开始下载时,不需要等它下载完成,即可执行其他操作。

什么是阻塞、非阻塞?

阻塞、非阻塞是从程序执行对的角度来看:
阻塞:程序在等待某个操作完成期间,自身无法继续干别的事,则称该程序在操作上是阻塞的
非阻塞:程序遇到需要等待时,自身可以去干别的事,则称该程序在操作上是非阻塞的

什么是正向代理和反向代理?

正向代理:代理的是客户端(FQ就是正向代理,例如国外网站不能访问,我们先访问到一个代理,然后代理去拿到国外网站的数据返回给我们)
反向代理:代理的是服务端(我们发送的请求会被nginx(或者阿帕奇)代理,然后分发给某一台服务器,对于我们来说我们并不知道我们的请求被哪台服务器处理)(nginx在项目上线时用过)

黏包现象?

因为我们的tcp协议是流式协议,tcp客户端发送的数据就是一些没有结构的字节流一样流向服务端,多个数据报黏在一起,产生黏包现象。
应对方法:
1.每个包设置结束标志,http协议就采用/r/n作为结束符
2.每个包设置固定大小的头,头中包含包的大小

http协议详情,http协议版本,http一些请求头?

http协议特点:
(1)基于tcp的应用层协议
(2)无状态无连接,不会做会话保持,所以才出现了cookie
(3)基于请求响应,服务端不能主动发信息给客户端,于是才出现了websocket
协议详情:
(1)请求协议:
请求首行:请求方式(get,post(天然接口不幂等),retrieve,delete,update);请求地址:请求http版本号
请求头:key-value形式,具体的请求头:cookie,useragent(浏览器相关信息),referer(请求来自于哪个页面),x-forward-for(拿到客户端真实的IP);
请求体:编码方式
(2)响应协议:
响应头:响应状态码、跨域问题(如果是简单请求,我们可以在响应头中添加键值对:{'Access-Control-Allow-Origin':'发起请求的页面'})
响应体:html格式、json格式
协议版本:
(1)0.9:最初版本,仅支持GET请求
(2)1.0:每次tcp连接客户端只能发送一个请求,服务端响应之后就会关闭这次连接,下次请求需要重新建立tcp连接,也就是不支持keep-alive
(3)1.1:引入持久连接,也就是默认不关闭tcp连接,一次连接可以被多个请求复用,不用声明keep-alive,客户端和服务端发现对方一段时间没有活动,就会主动关闭连接(主流还是1.1)。
(4)2.0:引入了多路复用,在1.1版本中即时开启了长连接,请求发送也是串行发送的,对带宽的利用率不够。2.0采用了多路复用的方式,可以并行的发送多个请求。
(5)3.0:3.0版本弃用了TCP协议,使用了UDP协议的QUIC协议来实现。

tcp三次握手和四次挥手?

三次握手
第一次:客户端向服务端发送建立连接请求,【携带一个随机数】(SYN=1,seq=随机数)
第二次:服务端回应客户端的建立连接请求(ACK=1,ack=随机数+1),服务端发送建立连接请求(SYN=1,seq=另一个随机数)
第三次:客户端回应服务端的建立连接请求(ACK=1,ack=另一个随机数+1)
四次挥手
第一次:客户端向服务端发起断开连接的请求(FIN=随机数)
第二次:服务端收到后,回复这个请求(ACK=1,ack=随机数+1)
第三次:服务端向客户端发起断开连接的请求(FIN=另一个随机数)
第四次:客户端收到后,回复这个请求(ACK=1,ack=另一个随机数+1)

洪水攻击

同一时间有大量的客户端请求建立连接 会导致服务端一直处于SYN_RCVD状态,服务端接收到了大量的syn请求,处于rcvd状态

xss攻击是什么?

XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序

osi七层协议,哪七层,每层有哪些,TCP/IP五层结构

osi七层协议:应用层、表示层、会话层、传输层、网络层、数据链路层、物理连接层
五层结构:应用层、传输层、网络层、数据链路层、物理连接层
应用层:有http协议、https协议、ftp协议、dns协议
表示层:https=http+ssl/tls,ssl处于表示层,主要负责加密解密的工作
会话层:负责建立、管理和终止会话连接
传输层:tcp和udp协议属于这一层,端口属于这一层
网络层:ip协议属于这一层,规定了所有接入互联网对的计算机都必须有一个ip地址,类似于身份证号
数据链路层:规定了计算机出厂时必须有MAC地址;数据帧、数据报也属于这一层
物理连接层:确保计算机之间的物理连接介质

tcp和udp的区别?udp用在哪里了?

tcp是面向连接的可靠协议,udp是无连接的不可靠协议,都是处于传输层
(1)tcp协议也称可靠协议。提供的是端到端可靠的字节流,通信之前先建立连接,如果对方没有收到消息会反复发送。udp协议也称不可靠协议,udp是无连接的,发送之前不需要建立连接,是否收到消息也不进行回应,也不保证数据一定送达
(2)udp有较好的实时性,工作效率比tcp高,因为tcp正在传输数据之前需要先建立连接。udp适用于对高速传输和有实时性要求的通信
(3)UDP 的标头大小为 8 个字节,TCP 标头大小为 20 字节。UDP 适合一次性传输较小数据的网络应用,如 DNS,SNMP等。
(4)TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流,UDP 是面向报文的一次交付一个完整的报文,报文不可分割,报文是 UDP 数据报处理的最小单位
udp:一些聊天软件、dns协议也用的是udp协议
tcp:http、mysql、redis客户端服务通信

wsgi,uwsgi,uWSGI,cgi,fastcgi分别是什么?

CGI:通用网关接口,定义了客户端和服务端如何传数据
FASTCGI:快速通用网关接口,是CGI的升级版,减少网页服务器与CGI程序之间的互动开销,从而使服务器可以同时处理更多的网页请求。常见的FASTCGI:Apache,Nginx
wsgi:定义web服务器和web框架之间的接口标准
uWSGI:一个web Server即一个实现了wsgi协议的服务器,处理发来的请求及返回响应
uwsgi:是uWSGI自有的一个协议,定义传输数据的类型

websocket协议?

websocket是一种通信协议,区别于http请求,可在单个tcp连接上进行双工通信,允许服务端主动向客户端推送数据。浏览器和服务器只需要完成一次tcp连接,两者之间就可以建立持久性的连接,并且进行双向数据传输
使用场景:只要涉及服务端主动给客户端发送信息,就需要使用到wedsocket,例如:实时聊天、服务端发送变化,主动向客户端发送通知(流程审批)
使用:django中使用channles模块实现

为什么有了gil锁还要互斥锁?

gil锁全称全局解释器锁,是解释器级别的锁,gil锁本质也是一个互斥锁。是一个简单的机制确保同一时间只有一个线程访问内存,线程要执行首先要获得gil锁。但它并不是为了数据安全设计的。
互斥锁是程序级别的锁,为了保证多线程并发操作数据而设置的锁,保证在加锁和释放锁之间,其他线程不能操作。
互斥锁操作:获得锁:Lock.acquire();释放锁:Lock.release()
例子1:一个进程下有两个线程t1和t2,它们都要去修改全局变量data。假设t1获得gil锁,此时gil抢到了互斥锁。碰巧在修改之前t1遇到了io操作(或者时间片到了),那么gil锁就会被释放被t2抢到,如果t1没有互斥锁那么此时t2直接可以修改data。有了互斥锁的存在此时t2也只能释放gil锁,t1获得cpu可以直接修改data。
例子2:全局的a=0,线程1和线程2都要去修改全局的a,序号代表执行顺序:
线程1:
(1).线程1拿到gil锁
(2).读取a=0
(3).cpu时间片到了,释放gil锁,释放cpu
(4).等待下次被调度执行
(10).轮到线程1执行,计算a+1
(11).将结果赋值给a,a=1
(12).释放gil锁
线程2:
(5).线程2获得了gil锁
(6).读取a=0
(7).计算a+1
(8).把结果赋值给a,此时全局a=1
(9).释放gil锁
以上两个例子说明如果没有互斥锁,会导致数据错乱,出现并发安全问题
但是我们不可能给一个函数中所有的代码都加上锁,这样会降低代码执行的效率。我们将出现并发安全问题的这段代码称为临界区,加锁也要在临界区加锁。上述例子2中的的临界区为:
"""
计算a+1
把结果赋值给a,此时全局a=1
"""

乐观锁和悲观锁?

乐观锁和悲观锁它们都是一种思想,都是人们定义出来的概念,和语言无关
并发控制:当程序出现并发的问题时,我们需要保证在并发情况下数据的准确性,以保证当前用户在和其他用户一起操作时,得到的结果和他单独操作时得到的结果是一样的,没有做好并发控制,就可能导致脏读、幻读、不可重复读等问题
悲观锁:当要对一条数据进行修改时,为了避免数据同时被其他人修改,最好的办法,最好的方法就是直接对该数据进行加锁,让并行变成串行,其他线程想要访问数据时需要阻塞挂起,互斥锁就属于悲观锁
乐观锁:总是假设最好的情况,每次拿数据都认为别人不会修改,所以不会上锁,只在更新的时候会判断以下在此期间别人有没有更新这个数据,如果更新了,我们就不会修改
乐观锁的实现:
CAS:即比较并替换,是解决多线程并行情况下使用锁造成性能损耗的一种机制。CAS 操作包含三个操作数——内存位置(V)、预期原值(A)和新值(B),执行CAS操作的时候,将内存位置的值与预期原值比较,如果相匹配,那么处理器会自动将该位置值更新为新值,否则,处理器不做任何操作。CAS会出现ABA的问题:比如我们准备对一个数据进行修改,这个数是1,在准备修改和提交的这段时间内,另一个事物已经将数字修改成了2,然后再修改为1,那么虽然我准备修改的数字是1,但是已经不是原来的那个1了。
解决ABA问题,我们需要对数据增加一个版本控制字段,只要有人动过这个数据,就将版本增加,修改一次版本是1,在修改一次版本是2,就说明这个数字有人动过。
版本号控制就是典型的CAS的应用:在数据表中增加一个版本号字段,每次更新数据时将版本号加1,同时将当前版本号作为更新条件,如果当前版本号与更新时的版本号一致,则更新成功,否则更新失败
使用场景:
并发量:如果并发量不大,可以使用悲观锁解决并发问题,如果并发量非常大的话,悲观锁会产生很严重的性能问题
响应速度:要求响应速度搞,建议使用乐观锁,成功就成功,失败就失败
冲突频率:冲突频率很高建议使用悲观锁
重试代价:重试代价大,建议使用悲观锁
读多写少:推荐使用乐观锁

python的可变和不可变数据类型是什么?

可变和不可变数据类型是描述数据类型的一种方式。
可变数据类型是当数据类型中的某个数据发生改变时,该数据类型绑定的内存地址不发生改变。可变类型有列表、字典、集合
不可变数据类型是当数据值发生改变时,绑定的内存地址也发生改变,也就是产生一个新的值.不可变类型有数字、字符串、元组

深浅拷贝

 	深浅拷贝是指在复制对象时,是否复制其子对象。
    浅拷贝只复制对象本身,而不复制其子对象,而深拷贝则会递归复制对象及其子对象。在Python中,浅拷贝创建一个新对象,但是只复制原始对象的基本数据类型和对象的引用,而不复制对象的子对象。这意味着,如果原始对象包含可变对象(例如列表、字典等),则新对象和原始对象将共享这些可变对象。因此,如果在新对象上进行更改,则原始对象也会受到影响。另一方面,深拷贝创建一个新对象,并递归复制原始对象及其所有子对象。这意味着,如果原始对象包含可变对象,则新对象将包含与原始对象完全相同的副本,而不是共享它们。因此,如果在新对象上进行更改,则原始对象不会受到影响。

django请求生命周期?

django请求生命周期是指用户在输入url到用户看到网页的这个时间段,django后台所发生的事
(1)django中封装了wsgi服务器,监听端口接受本次请求,然后将请求交给框架(django)
(2)传送消息到中间件
(3)对请求进行校验或处理,再传送到路由系统中进行路由分发,匹配到对应对的视图函数或者视图类
(4)将请求传输到这个视图函数或者视图类中,进行业务逻辑的判断和处理
(5)调用models中表对象,通过orm拿到数据
(6)将封装了response的响应传输到中间件
(7)通过wsgi再进行封装处理,响应数据到浏览器展示给用户

django中的信号如何使用,有哪些作用?

django的信号提供了一种通知机制,他是设计模式中的观察者模式(发布订阅模式),在发生变化的时候自动触发某个函数的执行
使用:例如我们只要在某个表中插入数据时,就删缓存
内置信号:如果是内置信号用起来简单,只需要写个函数,跟内置信号绑定,当信号被触发,函数就会执行

Django提高查询效率对的方法有哪些?

(1)首先每个app中models中的表不能太多,一般不超过5个
(2)Django中默认惰性查询,只要查询结果是queryset,不打印执行结果,那么就不会走sql语句。我们可以使用only和defer关键字,它们都可以点括号内的名字,only查询括号内的字段不需要走sql语句,查括号内没有的字段需要走sql语句。defer刚好相反,查括号内有的字段会走sql语句,查括号内没有的字段会走sql语句。
(3)使用select_related对一对一和一对多的外键关系进行查询。第一次查询的时候它会查询到包含外键的所有字段信息,并且很消耗性能。但是之后的查询就不走数据库

django orm如何优化?

(1)给字段添加索引
(2)在查询大量数据,并且只需要查询一次时使用QuerySets的iterator(),不会产生缓存
(3)在允许的情况下一次性取出所有数据,使用defer和only
(4)统计数量时用QuerySet.count()代替len(queryset)
(5)在判断queryset时,在queryset末尾点exists()结果会变成一个布尔值。有值是True,没有值是False,执行效率高于if判断
(5)queryset.update()或者delete()可以一次性处理多条数据,无需一条条处理
(6)如果批量插入多条数据,可以使用bulk_create()
(7)一对一和一对多使用select_related(),多对对使用prefetch_related()

django是如何保证运行安全的?

(1)跨站请求伪造:为了防止请求页面不是恶意请求,需要添加csrf唯一标识。csrf保护的工作原理是检测每个POST请求的随机数,确保了恶意用户不能随意发送恶意请求。
(2)sql注入保护:当我们用django写原生sql校验时,例如校验用户名和密码,如果用户名存在,并且后面加了--(sql当中的注释),那么同样会校验通过。所以我们在django使用原生sql时需要使用cursor.execute(原生sql语句,(username, userpwd))来防止sql注入问题
(3)django可以通过请求头中的referer拿到是哪个页面发送了请求,通过限制策略可以保护用户的隐私

drf中有哪些视图类?

(1)View:视图类在路由系统中会.as_view(),在View中有一个as_view()方法,该方法的返回值是view。所以类名点as_view()相当于类名点view。在as_view()方法中有一个view方法,该方法的返回值是self.dispatch(request, *args, **kwargs),self是视图类的对象,在View类中可以找到dispatch方法,在dispatch方法中通过反射(handler = getattr(self, request.method.lower(), self.http_method_not_allowed))拿到了视图类中的get()方法和post()方法。所以我们在继承View类写接口时候需要在类中定义get()或post()或者其他需要的方法。
(2)APIView:APIView继承了View。类名点as_view(),as_view()方法在APIView中可以找到,并且返回了屏蔽csrf校验的view方法。view方法依旧是View中的闭包函数view,返回dispatch,但是这次的dispatch不在View中而是在APIView中就可以找到,在这里进行三大认证并且封装了最新的request,然后再去视图类中通过反射拿到get()和post()方法等。

orm中的value和value_list有什么区别?

value和value_list都跟在queryset后面,括号内跟一个或多个查询的字段名,查询的结果都是queryset。value的查询结果包含查询的字段名,value_list不包含字段名

如何自定义异常类?

写一个类继承Exception,重写init方法
class NameDoesNotExist(Exception):
def init(self,message,code):
    self.code=code
    super().init(message)

文件操作怎样控制光标移动?

seek

python代码如果部署在用户的服务器上,如何保证代码不泄露?

(1)代码运行起来之后删除项目(代码运行起来运行在内存中,只要不关机就不会停止服务)
(2)pipinstaller运行成可执行文件

字典查询10条数据与十万条数据有什么差异

1.时间延迟:查询10条数据通常会在几毫秒内完成,而查询十万条数据可能需要几秒钟或几分钟的时间。
2.内存占用:十万条数据将比10条数据占用更多内存,特别是如果数据集非常庞大时。
3.索引维护:当数据量增加时,字典的索引维护可能会比较困难,并需要使用更复杂的算法。
4.查询精度:查询更多的数据通常会带来更高的查询精度和准确性。
5.搜索结果:当查询十万条数据时,在结果中往往包含更多的相关内容,对于用户来说更有价值。
6.加载速度:加载十万条数据通常需要更长的时间,这可能会影响用户的体验

python中的>>和<<是什么意思?

>>相当于前面的数除以2的后面的数次方
<<相当于前面的数乘以2后面的数的次方
print(100>>3) # 相当于100除以2的三次方
print(3<<3) # 24
print(5<<3) # 40

reduce和map怎么使用?

reduce的工作过程是 :在迭代序列的过程中,首先把 前两个元素(只能两个)传给 函数,函数加工后,然后把 得到的结果和第三个元素 作为两个参数传给函数参数, 函数加工后得到的结果又和第四个元素 作为两个参数传给函数参数,依次类推。reduce函数中有两个参数,第一个是运算的法则,第二个参数是函数或者迭代器:
map()方法会将 一个函数 映射到序列的每一个元素上,生成新序列,包含所有函数返回值。也就是说序列里每一个元素都被当做x变量,放到一个函数f(x)里,其结果是f(x1)、f(x2)、f(x3)......组成的新序列:

django中的session的底层实现原理?

设置session:request.session['k1'] = 'xxx'
获取session:request.session.get('k1')
设置session之后底层原理:
django内部产生一个随机字符串,操作django_session表(就是存session的地方),给客户端返回一个名为session_id的随机字符串cookie。
在中间件SessionMiddleware的process_response()方法内,
首先取出request.session的modify属性,判断是否是true,如果是true,表示在视图函数中修改过session,数据库同步修改;
如果是false,就不修改,返回给前端sessionid:随机字符串;
请求来的时候:
自动从浏览器请求中获取sessionid对应的随机字符串
拿着该随机字符串去django_session表中查找对应的数据
如果比对上了,则将对应的数据取出并以字典的形式封装到request.session中;如果比对不上 则request.session.get()返回的是None
在中间件SessionMiddleware的process_request()方法内,
通过sessionid获取水机字符串,拿这个随机字符串查找存放session的数据库表,
将查找到的session字典结果存放在request.session中
session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME)
request.session = self.SessionStore(session_key)

get请求和post请求的区别?

(1)post请求更安全,请求的信息不会作为url的一部分,不会保存在浏览器浏览记录中
(2)get请求有url长度的限制,post发送的请求更大
(3)post请求能发送更多的数据类型,get请求只能发送ASCII字符
(4)post请求速度比get请求更慢
(5)post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作

django中整形的数据类型分别表示的范围?

IntegerField:整形(4个字节,32位0或1),表示数字个数:232,表示范:-231-2^31-1
BigIntegerField:整形(8个字节,64位0或1),表示数字个数:264,表示范围:-263-2^63-1
SmallIntegerField:整形(2个字节,16位0或1),表示数字个数:216,表示范围:-215-2^15-1

redis的底层的数据?

String的底层是(简单动态字符串)
List的底层是(双向链表和压缩链表)
Hash的底层是(压缩链表和哈希表)
Set的底层是(整数数组和哈希表)
Sorted Set底层(压缩链表和跳表

redis持久化方案有哪些?

(1).RDB:通过save生成RDB持久化,通过bgsave异步生成持久化
(2).AOF:客户端每写入一调命令,都会记录一条日志,放到日志文件中,如果出现宕机,可以将数据完全恢复
随着命令的逐步写入,并发量的变大, AOF文件会越来越大,通过AOF重写来解决该问题。本质就是把过期的,无用的,重复的,可以优化的命令,来优化,这样可以减少磁盘占用量,加速恢复速度

celery异步任务执行的流程?

1.创建一个 Celery 实例,填入关键三个参数:broker, backend, include
2.在 include 中注册 task 文件,在该文件内编写任务,使用 Celery 实例装饰(如:@app.task)
3.使用 delay() 函数,将异步任务推入 Celery 任务队列。
4.当推入队列的异步任务被处理时,Celery 会去寻找可用的 worker 来运行任务。
5.任务在 worker 上执行完成后,worker 会将结果存储到 backend(如 Redis 或数据库等)。
6.访问另一个接口,获取该结果。

总之,异步任务的执行流程如下:创建任务 -> 推入任务队列 -> 执行任务 -> 返回结果 -> 查询结果

linux常用命令

ps aux:查看进程
netstat nlp |grep 端口号:查看端口占用情况
kill -9 进程号:强制停掉进程
查看内存:cat /proc/meminfo、free -h
ping:查看与服务端的连接状态
echo:将文本写入文件
hostname -l:显示网络IP地址
ip addr show:显示IP地址
ifconfig:显示虚拟机IP地址
sudo chmod -R 777 [文件] 赋予文件权限

linux中find 与 grep 的区别?

如果你需要搜索文件系统中的文件和目录,那么使用 find 是更合适的选择。
如果你需要在文件中搜索文本,那么使用 grep 更加适合

Mysql基础

1、 FROM:对FROM子句中的前两个表执行笛卡尔积(交叉联接),生成虚拟表VT1。
2、 ON:对VT1应用ON筛选器,只有那些使为真才被插入到TV2。
3、 OUTER (JOIN):如果指定了OUTER JOIN(相对于CROSS JOIN或INNER JOIN),保留表中未找到匹配的行将作为外部行添加到VT2,生成TV3。如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表位置。
4、 WHERE:对TV3应用WHERE筛选器,只有使为true的行才插入TV4。
5、 GROUP BY:按GROUP BY子句中的列列表对TV4中的行进行分组,生成TV5。
6、 CUTE|ROLLUP:把超组插入VT5,生成VT6。
7、 HAVING:对VT6应用HAVING筛选器,只有使为true的组插入到VT7。
8、 SELECT:处理SELECT列表,产生VT8。
9、 DISTINCT:将重复的行从VT8中删除,产品VT9。
10、 ORDER BY:将 VT9中的行按ORDER BY子句中的列列表顺序,生成一个游标(VC10)。
11、 TOP:从 VC10的开始处选择指定数量或比例的行,生成表TV11,并返回给调用者。 where子句中的条件书写顺序
聚合函数:
   AVG(col)返回指定列的平均值
   COUNT(col)返回指定列中非NULL值的个数
   MIN(col)返回指定列的最小值
   MAX(col)返回指定列的最大值
   SUM(col)返回指定列的所有值之和
   GROUP_CONCAT(col) 返回由属于一组的列值连接组合而成的结果
数学函数:
   ABS(x) 返回x的绝对值
   BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制)

数据库三大范式

第一范式(1NF):保证数据库中每一列必须具有原子性,也就是数据表中的每一个字段都是不可再拆分的最小数据单元。
第二范式(2NF):在满足第一范式的基础上,如果表是单主键,那么主键以外的列必须完全依赖于主键。如果表是复合主键,那么主键以外的列必须完全依赖于主键,并且不能依赖于主键的一部分(其中一个或几个字段)。
第三范式(3NF):在满足第二范式的基础上,表中每一个非主键列都必须和主键直接相关,非主键列和主键之间不能传递依赖,它们之间是相互独立的。

mysql有哪些索引类型,分别有什么作用?

1.普通索引是mysql中最基本的索引类型,它没有任何限制,唯一的任务就是加快对数据库的访问速度。普通索引允许在定义索引的列中插入重复值和空值。
举例:在 tb_student 表中的 id 字段上建立名为 index_id 的索引:
CREATE INDEX index_id ON tb_student(id);
2.唯一索引:不是为了提高访问速度而是为了避免数据重复。唯一索引的值必须唯一,允许有空值。如果是组合索引,那么组合的值必须唯一。创建唯一索引通常使用 UNIQUE 关键字
CREATE UNIQUE INDEX index_id ON tb_student(id);
3.主键索引(聚簇索引):专门为主键字段创建的索引,也属于索引的一种。主键索引是一种唯一索引,如果不存在主键,隐藏一个主键,不允许重复或者为空。创建主键索引通常使用 PRIMARY KEY 关键字。不能使用 CREATE INDEX 语句创建主键索引。
4.联合索引(组合索引或多列索引):组成主键的字段为多个,多个字段组成唯一的索引。
5全文索引:是一种用于快速搜索文本内容的索引类型。它允许在文本列中进行关键字搜索,而不仅仅是普通的字符串匹配。使用全文索引可以提高搜索性能,并且支持高级搜索功能
    
全文索引满足一下条件:
    表必须使用MyISAM存储引擎
    要创建全文索引的列必须使用CHAR、VARCHAR或TEXT类型
    要创建全文索引的列必须是表的一个普通列,而不能是主键或唯一键

mysql当中的索引什么时候会失效?

1.违反最左前缀法则
如果索引有多列,要遵守最左前缀法则
即查询从索引的最左前列开始并且不跳过索引中的列
2.在索引列上做操作:计算、函数、自动手动转换类型
3.使用不等号:!= <>
4.like以通配符开头('%abc')

什么是事务,MySQL是如何支持事务的?

 事务就是一段sql语句的批处理,但是这个批处理是一个原子 ,不可分割,要么都执行,要么回滚(rollback)都不执行。
事务具体四大特性,也就是经常说的ACID :
1.原子性:所有操作要么全部成功,要么全部失败回滚
2.一致性:事务执行之前和执行之后都必须处于一致性状态。
3.隔离性:数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离
4.持久性:一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,
即使遭遇故障依然能够通过日志恢复最后一次更新在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务

MYSQL 事务处理主要有两种方法:
	1、用 BEGIN, ROLLBACK, COMMIT来实现 BEGIN 开始一个事务 ROLLBACK 事务回滚 COMMIT 事务确认
	2、直接用 SET 来改变 MySQL 的自动提交模式: SET AUTOCOMMIT=0 禁止自动提交 SET AUTOCOMMIT=1 开启自动提交

事务的隔离级别:
	1.read uncommitted(未提交读):事务中的修改即使没有提交,对其他事物也都是可见的。事务可以读取未提交的数据,这一点也称为‘脏读’。
	2.read committed(提交读):大多数数据库默认的隔离级别。一个事务从开始直到提交之前所做的任何操作对其他事物都是不可见的,事务中的数据如果没有最终提交,对其他事物可见的都是硬盘当中真正的数据。解决了脏读和数据丢失,但会出现一个事务范围内两个相同的查询出现了不同的结果,也就是不可重复读。
	3.repeatable read(可重复读,mysql默认的隔离级别):在开始读取数据(事务开启)时,不再允许修改操作,这样就可以保证在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,能够解决‘脏读’(因为读期间不能进行修改操作),不能解决‘幻读’(依然可以允许增加操作)。幻读是指当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插了新的记录,所以我原来的事物再次插入这条重复的数据时无法插入。InnoDB和XtraDB通过多版本并发控制(MVCC)及间隙锁策略解决该问题
	4.serializable(可串行化):强制事务串行执行,很少使用该级别。一个事务执行完毕之后再执行另一个事物,执行效率低。可以避免脏读、不可重复读、幻读。
   

脏读、不可重复读、幻读是什么?mysql5.7以后默认的隔离级别是什么?

 	脏读:指的是读到了其他事务未提交的数据,未提交意味着这些数据可能会回滚,也就是可能最终不会存到数据库中,也就是不存在的数据。读到了并一定最终存在的数据,这就是脏读
	不可重复读:指的是在一个事务内,最开始读到的数据和事务结束前的任意时刻读到的同一批数据出现不一致的情况
	幻读:并不是说两次读取获取的结果集不同,幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些:select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,此时就发生了幻读

左连接,右连接,内连接,全连接是什么?

数据通常不在一个表中,这就涉及到连表操作,表间联系的方式有很多:
左连接:以左表为基准,将左表所有的数据展示出来,按照on后面的对应条件分别对应右表中的数据,没有值就用空补齐
右连接:以右表为基准,将右表中所有的数据展示出来,按照on后面的对应条件分别对应左表中的数据,没有值就用空补齐
全连接:以左右两表数据为基准,左右两表的数据都展示,没有的数据用空替代

union和union all的区别?

 union和union all前后都跟select出来的结果。union会自动对取出的数据进行去重,并且进行排序。union all不会去除重复的数据

如何开启慢日志查询?

1 执行 SHOW VARIABLES LIKE “%slow%”,获知 mysql 是否开启慢查询 slow_query_log 慢查询开启状态 OFF 未开启 ON 为开启 slow_query_log_file 慢查询日志存放的位置(这个目录需要MySQL的运行帐号的可写权限,一般设置为MySQL的数据存放目录)
2 修改配置文件( 放在[mysqld]下),重启 long_query_time 查询超过多少秒才记录
3 测试是否成功
4 慢查询日志文件的信息格式

什么是qps,tps,并发量,pv,uv

-qps:Queries Per Second,每秒查询率,一台服务器每秒能够响应的查询次数
-tps:Transactions Per Second,是每秒处理的事务数,包括一条消息入和一条消息出,加上一次用户数据库访问
-并发量:系统同时处理的请求数量
-PV(Page View):页面访问量,即页面浏览量或点击量,用户每次刷新即被计算一次。可以统计服务一天的访问日志得到
-UV(Unique Visitor):独立访客,统计1天内访问某站点的用户数。可以统计服务一天的访问日志并根据用户的唯一标识去重得到
-DAU(日活)DAU(Daily Active User),日活跃用户数量。常用于反映网站、app、网游的运营情况。DAU通常统计一日(统计日)之内,登录或使用了某个产品的用户数(去除重复登录的用户),与UV概念相似
-MAU(Month Active User):月活跃用户数量,指网站、app等去重后的月活跃用户数量

数据库怎么优化查询效率?

1、储存引擎选择:如果数据表需要事务处理,应该考虑使用InnoDB,因为它完全符合ACID特性。
如果不需要事务处理,使用默认存储引擎MyISAM是比较明智的
2、分表分库,主从。
3、对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
4、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
5、应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
6、应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描
7、Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志
8、对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。

数据库的优化?

1.优化索引、SQL 语句、分析慢查询;
2.设计表的时候严格根据数据库的设计范式来设计数据库;
3.使用缓存,把经常访问到的数据而且不需要经常变化的数据放在缓存中,能节约磁盘IO
4.优化硬件;采用SSD,使用磁盘队列技术(RAID0,RAID1,RDID5)等
5.采用MySQL 内部自带的表分区技术,把数据分层不同的文件,能够提高磁盘的读取效率;
6.垂直分表;把一些不经常读的数据放在一张表里,节约磁盘I/O;
7.主从分离读写;采用主从复制把数据库的读操作和写入操作分离开来;
8.分库分表分机器(数据量特别大),主要的的原理就是数据路由;
9.选择合适的表引擎,参数上的优化
10.进行架构级别的缓存,静态化和分布式;
11.不采用全文索引;
12.采用更快的存储方式,例如 NoSQL存储经常访问的数据**。

Mysql集群的优缺点?

优点:
    99.999%的高可用性
    快速的自动失效切换
    灵活的分布式体系结构,没有单点故障
    高吞吐量和低延迟
    可扩展性强,支持在线扩容
缺点:
    存在很多限制,比如:不支持外键
    部署、管理、配置很复杂
    占用磁盘空间大、内存大
    备份和恢复不方便
    重启的时候,数据节点将数据load到内存需要很长的时间

你用的Mysql是哪个引擎,各引擎之间有什么区别?

主要 MyISAM 与 InnoDB 两个引擎,其主要区别如下:
InnoDB 支持事务,MyISAM 不支持,这一点是非常之重要。事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而 MyISAM就不可以了;
MyISAM 适合查询以及插入为主的应用,InnoDB 适合频繁修改以及涉及到安全性较高的应用;
InnoDB 支持外键,MyISAM 不支持;
MyISAM 是默认引擎,InnoDB 需要指定;
InnoDB 不支持 FULLTEXT 类型的索引;
InnoDB 中不保存表的行数,如 select count() from table 时,InnoDB;需要扫描一遍整个表来计算有多少行,但是 MyISAM 只要简单的读出保存好的行数即可。注意的是,当 count()语句包含 where 条件时 MyISAM 也需要扫描整个表;
对于自增长的字段,InnoDB 中必须包含只有该字段的索引,但是在 MyISAM表中可以和其他字段一起建立联合索引;清空整个表时,InnoDB 是一行一行的删除,效率非常慢。MyISAM 则会重建表;
InnoDB 支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%'

Mysql数据库如何分区、分表?

分表可以通过三种方式:Mysql集群、自定义规则和merge存储引擎。
分区有四类:
RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区。
LIST 分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个
值来进行选择。
HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的
这些行的列值进行计算。这个函数可以包含MySQL 中有效的、产生非负整数值的任何表达式。
KEY 分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL 服务器
提供其自身的哈希函数。必须有一列或多列包含整数值。

Sql注入是如何产生的,如何防止?

程序开发过程中不注意规范书写sql语句和对特殊字符进行过滤,导致客户端可以通过全局变量
POST和GET提交一些sql语句正常执行。产生Sql注入。下面是防止办法:
a. 过滤掉一些常见的数据库操作关键字,或者通过系统函数来进行过滤。
b. 在PHP配置文件中将Register_globals=off;设置为关闭状态
c. SQL语句书写的时候尽量不要省略小引号(tab键上面那个)和单引号
d. 提高数据库命名技巧,对于一些重要的字段根据程序的特点命名,取不易被猜到的
e. 对于常用的方法加以封装,避免直接暴漏SQL语句
f. 开启PHP安全模式:Safe_mode=on;
g. 打开magic_quotes_gpc来防止SQL注入
h. 控制错误信息:关闭错误提示信息,将错误信息写到系统日志。
i. 使用mysqli或pdo预处理。

NoSQL和关系数据库的区别?

a. SQL数据存在特定结构的表中;而NoSQL则更加灵活和可扩展,存储方式可以省是JSON文档、哈希表或者其他方式。
b. 在SQL中,必须定义好表和字段结构后才能添加数据,例如定义表的主键(primary key),索引(index),触发器(trigger),存储过程(stored procedure)等。表结构可以在被定义之后更新,但是如果有比较大的结构变更的话就会变得比较复杂。在NoSQL中,数据可以在任何时候任何地方添加,不需要先定义表。
c. SQL中如果需要增加外部关联数据的话,规范化做法是在原表中增加一个外键,关联外部数据表。而在NoSQL中除了这种规范化的外部数据表做法以外,我们还能用如下的非规范化方式把外部数据直
接放到原数据集中,以提高查询效率。缺点也比较明显,更新审核人数据的时候将会比较麻烦。
d. SQL 中可以使用JOIN表链接方式将多个关系数据表中的数据用一条简单的查询语句查询出来。NoSQL暂未提供类似JOIN的查询方式对多个数据集中的数据做查询。所以大部分NoSQL使用非规范化的数据存储方式存储数据。
e. SQL中不允许删除已经被使用的外部数据,而NoSQL中则没有这种强耦合的概念,可以随时删除任何数据。
f. SQL中如果多张表数据需要同批次被更新,即如果其中一张表更新失败的话其他表也不能更新成功。这种场景可以通过事务来控制,可以在所有命令完成后再统一提交事务。而NoSQL中没有事务这个概念,每一个数据集的操作都是原子级的。
g. 在相同水平的系统设计的前提下,因为NoSQL中省略了JOIN查询的消耗,故理论上性能上是优于SQL的。

Dockerfile用过吗?常永命令有哪些?

Dockerfile是由一系列命令和参数构成的脚本文件,可以不基于容器而直接构件出一个新的镜像。
命令:
FROM centos:7 # 基于centos:7构建出来
MAINTAINER max # 镜像创建者是max
ENV name max # 设置环境变量
RUN ... # 输入命令
WORKDIR 目录 # 创建一个目录,以后执行命令就在这个目录下,并且我们一进来就在该目录下

如何理解python中函数被称为一等公民?

在Python中,函数被称为一等公民(first-class citizens),这意味着函数可以像其他数据类型一样进行操作,例如可以赋值给变量、作为参数传递、作为返回值返回等

标签:__,面试题,请求,后端,python,对象,线程,数据,函数
From: https://www.cnblogs.com/bnmm/p/17372182.html

相关文章

  • python调用c程序
    C代码文件名《task.c》#include<stdio.h>inttask(intn,intp,intm){ inti,j,k; unsignedlongs=0; for(i=0;i<n;i++){ for(j=0;j<p;j++){ for(k=0;k<m;k++) { s=s+i+j+k; } }} returns;}编译在task.c文件目录上打开命令行......
  • python_数据分析与挖掘实战_词云
    #-*-coding:utf-8-*-#代码12-1评论去重的代码importpandasaspdimportreimportjieba.possegaspsgimportnumpyasnp#去重,去除完全重复的数据reviews=pd.read_csv("../../data/0404/reviews.csv")reviews=reviews[['content','content_type']......
  • 告别繁冗,走向专业!前后端分离部署的主要内容介绍
    当前,前后端分离已经成为行业发展趋势。那么,什么是前后端分离?前后端分离部署的内容都有哪些?如果想告别繁冗,朝着更专业、更简洁的方向迈进,那么,做好前后端分离也是顺其自然的事。今天,我们就一起来探讨前后端分离部署的相关内容知识,希望能给屏幕前的你一些启发。1、什么是前后端分离?......
  • 4D成像毫米波雷达点云数据集VOD(含Python和MATLAB数据解析仿真代码)
    公众号【调皮连续波】【正文】编辑|  调皮哥的小助理     审核|调皮哥1、引言4D成像雷达开源数据集,其实好用的并不多,VOD数据集我个人感觉还可以。这其实也在之前分享过,但是为了更加清楚地展示这个数据集如何使用,本期文章就简单做个分享。在MATLAB环境下可以得到以下的......
  • python 魔术方法
    在Python中,魔术方法(也称为特殊方法或双下划线方法)是一组预定义的方法,它们被用于在类中实现特定的行为。这些方法以两个下划线开头和结尾,例如__init__()和__str__()。以下是几个常见的魔术方法及其作用:__init__():用于初始化类的实例。当创建类对象时,这个方法会自动调用。__st......
  • Python保留两位小数五种常用的方法!
    在Python中,保留两位小数是我们经常会碰到的问题,也是比较常见的需求之一。那么Python中如何保留两位小数?Python保留两位小数的方法有很多种,具体请看下文。1、使用字符串格式化大部分语言都可以使用字符串格式化的方法来实现保留两位小数,Python也不例外。a=12.345......
  • python 闭包、偏函数、数据锁定
    闭包(Closure)是指在一个函数内部定义另外一个函数,并且这个内部函数可以访问外部函数中的变量。通常情况下,当外部函数执行完毕后,局部变量会被销毁,但是闭包可以使得外部函数执行完毕后,其内部函数仍然可以访问外部函数的局部变量。比如下面这个例子:defouter(x):definner(y):......
  • python 多态
    在Python3中,多态是指同一个方法或者操作可以在不同的对象上产生不同的行为或结果。这意味着一个函数可以接受不同类型的参数,并且可以表现出不同的行为。生活中的例子如下:假设你想要买一台新电视机,你可能会去电器店看看有哪些电视可供选择。当你开始比较价格和功能时,你可能会发......
  • SDN Python编程创建多数据中心网络
    首先开启OpenDaylightcd/home/ubuntu/karaf-0.7.1/bin/./karaf新开一个终端执行以下操作在/home/ubuntu/mininet/examples目录下新建一个sdn4.py文件输入以下代码frommininet.topoimportTopoclassMyTopo(Topo):def__init__(self):Topo.__init......
  • python 迭代器和推导式的不同处
    迭代器和推导式都是在Python中用于处理可迭代对象的机制,但它们之间有一些关键区别。返回值类型不同:推导式返回一个新的数据结构(列表、集合、字典等),而迭代器返回一个迭代器对象。推导式生成的是一个新的序列或集合,而迭代器则是逐个生成元素。实现方式不同:推导式是一种高级语......