2024 python 求职 常见面试题(北京 爬虫/后端)

python 优缺点

开源,可移植,支持面向过程和面向对象,可扩展性,可嵌入性,库多

慢 用c重写重要部分,GIL

python程序运行过程

pyCodeObject 内存 到 pyc 硬盘持久化存储 pyc有long 存的是写入时间

pyc 中 存的是 import导入的可重用的模块

分号在python中的应用

可写可不写,一行定义多个值时使用

python中的变量利用del删除对应的内存空间的数值

变量会改变内存空间,常量不会

断言

断言可以在条件不满足程序运行的情况下直接返回错误,而不必等待程序运行后出现崩溃的情况

assert

实例变量就是一个用 self 修饰的变量。

深浅拷贝,赋值

深拷贝 完全拷贝了父对象和子对象 相当于在本地拷贝了一个副本 副本的变化不会影响到源文件中的数据

浅拷贝拷贝父对象,但是不会拷贝父对象的子对象 只能复制列表中的一维元素,二维拷贝不了
[1,2[1,2,3],4,5,6,7] 利用浅拷贝
***赋值:***其实就是对象的引用。

python 如何实现多线程

线程是一个轻量级的进程,多线程允许依次执行多个线程

GIL锁(全局解释锁)确保一次执行单个线程,一个线程保存GIL并在将其传递给下一个线程之前执行一些操作,这样就会产生并行执行的错觉,但是实际上,只是线程轮流在CPU上执行

threading.local的作用?

线程内的全局变量,只在同一个线程内可以调用,本质上是对全局字典对象管理类的一个封装

*args和**kwargs的区别(缺省参数)

*args传递元组/列表 不定长参数

**kwargs传递字典 关键字参数

***args和*kwargs都是用于函数中传递参数的,*args传递的是非键值对的参数,*kwargs传递的是带键值对的参数,如果还有普通参数需要传递,那么应该先传递普通的参数。

计算文件中的大写字母数

isupper() 检查是否时大写

islower() 检查是否时小写

istitle() 检查是否是标题格式

@ $ 这样的符号既满足大写又满足小写

img

img

img

如何随机打乱列表中的元素,要求不引用额外的内存空间

img

join 和 split的区别 ?

img

img

删除字符串多余空格

img

http 和 https ?

http: 端口 80

​ 超文本传输协议,信息明文传递

​ 连接简单,基于无状态的连接

https:

​ 端口 443

​ 具有安全协议的超文本传输协议,信息ssl密文传递

​ 由ssl+http协议构成的可以进行密文传输,身份认证的网络协议

​ https协议需要到ca机构申请ssl证书,免费证书较少,高级ssl证书 需要付费

状态码

2xx:200(get请求成功),201(post,put创建了一个资源),204(删除一个资源,服务器删除成功)

3xx:301(服务器永久移动,自动转发到新的位置),302(服务器临时移动,原服务器没有永久移除)俩者的最大区别为搜索引擎是否记录

4xx:400(客户端请求语法错误),403(服务器拒绝提供服务)404(客户端引用了不存在的资源)

5xx:500(服务器错误,拒绝请求),503(服务器当前不能处理客户请求,当前服务器不可用),504(请求超时,没有到达网关)

500,503,504常见场景

500:常见场景为编程语言语法错误,web脚本错误,高并发,打开文件数超过系统资源限制,一般解决思路为查看服务器nginx,python的错误日志,负载均衡,修复脚本错误

503:常见场景为服务器无法使用,一般为服务器超载或者是停机维护,解决思路为查看服务器系统资源或者确定服务器开启状态

502,504:常见场景为web服务器故障,程序进程不够,一般解决思路为查看nginx代理的问题,或者是nginx的conf配置相关

常见的HTTP方法有哪些?

get:请求指定的页面信息,返回实体主体;

head: 类似于get请求,只不过返回的响应中没有具体的内容,用于捕获报头;

post:向指定资源提交数据进行处理请求(比如表单提交或者上传文件),。数据 被包含在请求体中。

put: 从客户端向服务端传送数据取代指定的文档的内容;

delete:请求删除指定的页面;

connext:HTTP1.1协议中预留给能够将连接方式改为管道方式的代理服务器;

options: 允许客户端查看服务器的性能;

trace:回显服务器的请求,主要用于测试或者诊断。

  • 请求行:请求方法+http协议版本+URL
  • 请求头部:用键值对表示,如Accept-Charst:utf-8,指定客户端接收的字符集;
  • 空行:通知请求头部结束;
  • 请求数据:由数据头部信息和数据内容组成,数据头部规定了数据的类型、长度、编码等信息(post方法有请求数据,get方法不能发送请求数据)。

(3)响应后返回的数据信息:

  • 状态行:协议版本+状态码(如常见的404,500,200)+状态码文本描述;
  • 响应头部:用键值对表示;
  • 空行:表示响应头部结束;
  • 响应数据:服务器返回的数据内容和数据头部信息(head请求无响应数据)。

scrapy

整体架构

流程

1.引擎打开一个域名,蜘蛛处理这个域名,并让蜘蛛获取第一个爬取的URL。

2.引擎从蜘蛛那获取第一个需要爬取的URL,然后作为请求在调度中进行调度。

3.引擎从调度那获取接下来进行爬取的页面。

4.调度将下一个爬取的URL返回给引擎,引擎将他们通过下载中间件发送到下载器。

5.当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎。

6.引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。

7.蜘蛛处理响应并返回爬取到的项目,然后给引擎发送新的请求。

8.引擎将抓取到的项目项目管道,并向调度发送请求。

系统重复第二步后面的操作,直到调度中没有请求,然后断开引擎与域之间的联系

scrapy的去重原理 (指纹去重到底是什么原理)

需要将dont_filter设置为False开启去重,默认是False;
对于每一个url的请求,调度器都会根据请求的相关信息加密得到一个指纹信息,并且将指纹信息和set()集合中得指纹信息进行比对,如果set()集合中已经存在这个数据,就不在将这个Request放入队列中。如果set()集合中没有,就将这个Request对象放入队列中,等待被调度。

scrapy中间件有几种类

scrapy的中间件理论上有三种(Schduler Middleware,Spider Middleware,Downloader Middleware),在应用上一般有以下两种

  1. 爬虫中间件Spider Middleware

    主要功能是在爬虫运行过程中进行一些处理.

  2. 下载器中间件Downloader Middleware

    主要功能在请求到网页后,页面被下载时进行一些处理.

说一说redis-scrapy中redis的作用?

它是将scrapy框架中Scheduler替换为redis数据库,实现队列管理共享。

优点:

可以充分利用多台机器的带宽;

可以充分利用多台机器的IP地址。

scrapy和scrapy-redis的区别?

scrapy是一个爬虫通用框架,但不支持分布式,scrapy-redis是为了更方便的实现scrapy分布式爬虫,而提供了一些以redis为基础的组件

redis支持主从同步,而且数据都是缓存在内存中,所以基于redis的分布式爬虫,对请求和数据的高频读取效率非常高

什么是主从同步?

在Redis中,用户可以通过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate)另一个服务器,我们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave),当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行同步操作,也即是,将从服务器的数据库状态更新至主服务器当前所处的数据库状态

scrapy[默认深度优先]和requests的使用情况 ?

requests 是 polling 方式的,会被网络阻塞,不适合爬取大量数据

scrapy 底层是异步框架 twisted ,并发是最大优势

scrapy框架的运行机制 ?

从start_urls里面获取第一批url发送请求,请求由请求引擎给调度器入请求对列,获取完毕后,调度器将请求对列交给下载器去获取请求对应的响应资源,并将响应交给自己编写的解析方法做提取处理,如果提取出需要的数据,则交给管道处理,如果提取出url,则继续执行之前的步骤,直到多列里没有请求,程序结束。

什么是爬虫协议 ?

Robots协议(也称为爬虫协议、爬虫规则、机器人协议等)也就是robots.txt,网站通过robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。

Robots协议是网站国际互联网界通行的道德规范,其目的是保护网站数据和敏感信息、确保用户个人信息和隐私不被侵犯。因其不是命令,故需要搜索引擎自觉遵守。

爬虫常见问题

UA

设置IP访问频率,如果超过一定频率,弹出验证码

通过并发识别爬虫 有些爬虫的并发是很高的,统计并发最高的IP,加入黑名单(或者直接封掉爬虫IP所在C段)

请求的时间窗口过滤统计

限制单个ip/api token的访问量

识别出合法爬虫 对http头agent进行验证,是否标记为、百度的spider,严格一点的话应该判别来源IP是否为、baidu的爬虫IP,这些IP在网上都可以找到。校验出来IP 不在白名单就可以阻止访问内容。

蜜罐资源 爬虫解析离不开正则匹配,适当在页面添加一些正常浏览器浏览访问不到的资源,一旦有ip访问,过滤下头部是不是搜素引擎的蜘蛛,不是就可以直接封了。比如说隐式链接。

破解反爬虫机制的几种方法

设置下载延迟

禁止Cookie

使用user agent池

使用IP池

分布式爬取

模拟登录—浏览器登录的爬取

如何提高爬取效率 ?

爬虫下载慢主要原因是阻塞等待发往网站的请求和网站返回

采用异步与多线程,扩大电脑的cpu利用率;

采用消息队列模式

提高带宽

分布式原理?

多台机器多个spider 对多个 url 同时进行处理

需要计算的数据量大,任务多,一台机器搞不定或者效率极低,需要多台机器共同协作(而不是孤立地各做各的,所以需要通信),最后所有机器完成的任务汇总在一起,完成大量任务.

将一个项目拷贝到多台电脑上,同时爬取数据

分布式爬虫则是将多台主机组合起来,共同完成一个爬取任务,这将大大提高爬取的效率。

记住爬虫的本质是网络请求和数据处理,如何稳定地访问网页拿到数据,如何精准地提取出高质量的数据才是核心问题。

分布式爬虫主要解决什么问题?

面对海量待抓取网页,只有采用分布式架构,才有可能在较短时间内完成一轮抓取工作。

它的开发效率是比较快而且简单的。

分布式如何判断爬虫已经停止了?

request请求方式中的post、get有什么区别 ?

GET一般用于获取/查询资源信息,而POST一般用于更新资源信息

get是在url中传递数据,数据放在请求头中,post是在请求体中传递数据

get安全性非常低,post安全性较高,但是get执行效率却比Post方法好

模拟登陆原理 ?

因为http请求是无状态的,网站为了识别用户身份,需要通过cookie记录用户信息(用户、密码),这些信息都会在手动登陆时记录在post请求的form-data里,那么在爬虫时候只需要将这些信息添加到请求头里即可。

Session与Cookie区别和联系

cookie数据保存在客户端,session数据保存在服务器端。

Cookies是属于Session对象的一种。但有不同,Cookies不会占服务器资源,是存在客服端内存或者一个cookie的文本文件中;而“Session”则会占用服务器资源。所以,尽量不要使用Session,而使用Cookies。但是我们一般认为cookie是不可靠的,session是可靠地,但是目前很多著名的站点也都依赖cookie。有时候为了解决禁用cookie后的页面处理,通常采用url重写技术,调用session中大量有用的方法从session中获取数据后置入页面。

Cookies与Session的应用场景:
Cookies的安全性能一直是倍受争议的。虽然Cookies是保存在本机上的,但是其信息的完全可见性且易于本地编辑性,往往可以引起很多的安全问题。所以Cookies到底该不该用,到底该怎样用,就有了一个需要给定的底线。

编写函数的4个原则 ?

函数设计要尽量短小

函数声明要做到合理、简单、易于使用

函数参数设计应该考虑向下兼容

一个函数只做一件事情,尽量保证函数语句粒度的一致性

什么是Hash(散列函数)?

散列函数(英语:Hash function)又称散列算法、哈希函数,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,重新创建一个叫做散列值(hash values,hash codes,hash sums,或hashes)的指纹。散列值通常用一个短的随机字母和数字组成的字符串来代表

python函数重载机制?

函数重载主要是为了解决两个问题。

  1. 可变参数类型。

  2. 可变参数个数。

另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不同以外,其功能是完全相同的,此时才使用函数重载,如果两个函数的功能其实不同,那么不应当使用重载,而应当使用一个名字不同的函数。

好吧,那么对于情况 1 ,函数功能相同,但是参数类型不同,python 如何处理?答案是根本不需要处理,因为 python 可以接受任何类型的参数,如果函数的功能相同,那么不同的参数类型在 python 中很可能是相同的代码,没有必要做成两个不同函数。

那么对于情况 2 ,函数功能相同,但参数个数不同,python 如何处理?大家知道,答案就是缺省参数。对那些缺少的参数设定为缺省参数即可解决问题。因为你假设函数功能相同,那么那些缺少的参数终归是需要用的。

好了,鉴于情况 1 跟 情况 2 都有了解决方案,python 自然就不需要函数重载了。

python 中的闭包

如果一个内部函数里,对外界作用域(但不是在全局作用域)的变量进行引用,那么内部函数就是一个闭包

nonlocal 关键字修改闭包外层数据

闭包应用场景

有些函数只写一次,别的地方不用,那闭包吧

python是没有switch语句,但是可以用字典替代。其中就运用到了闭包

lambda函数式编程

运算符

位运算

和 & 同1为1 其他为0

或 | 遇1为1

异或 ^ 同为0,不同为1

取反 ~ 原码 反码 补码

最左边 符号位 1为负数,0为正数

正数 原码=反码=补码

负数 原码=符号位不变,其他按位取反=反码+1

元组的解封装

img

定义多个变量并且赋值

(1) a,b,c=1,2,3

(2) a=b=c=3

进程和线程的区别(进程>线程)

进程是资源分配的基本单位

线程是程序中执行的最小单位

进程有自己独立的内存空间,每启动一次进程,系统就会为它分配地址空间,建立数据表来维护代码段,堆栈段和数据段

线程是共享进程中的数据,使用相同的地址空间,因此cup切换一个线程花费的远比进程要小很多,同时创建一个线程的开销也比进程小很多

进程:from multiprocessing import pool

多进程适合在CPU 密集型操作(cpu 操作指令比较多,如位数多的浮点运算)。

线程:threading.Thread

多线程适合在IO 密集型操作(读写数据操作较多的,比如爬虫)。

进程之间的通信

最常用的进程间通信的方式有信号、信号量、消息队列、共享内存

多线程竞争

线程是非独立的,同一个进程里线程是数据共享的,当各个线程访问数据资源时会出现竞争状态即:数据几乎同步会被多个线程占用,造成数据混乱,即所谓的线程不安全。

那么怎么解决多线程竞争问题?

​ – 锁。 (限制多线程同时执行,保证同一时间只有一个线程执行)

*锁(Lock)是Python 提供的对线程控制的对象。有 互斥锁、可重入锁、死锁

**锁的好处:**确保了某段关键代码(共享数据资源)只能由一个线程从头到尾完整地执行能解决多线程资源竞争下的原子操作问题。 锁在多线程和多进程中起到一个同步的作用,以保护每个线程和进程必要操作的完整执行。

锁的坏处:阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了 锁的致命问题:死锁。

创建多线程或多进程,都必须要先经过主模块判断,即必须在if name==‘main’:语句之后才行,这是为了保护资源的一种强制性机制

线程安全,互斥锁?

每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

同一个进程中的多线程之间是共享系统资源的,多个线程同时对一个对象进行操作,一个线程操作尚未结束,另一个线程已经对其进行操作,导致最终结果出现错误,此时需要对被操作对象添加互斥锁,保证每个线程对该对象的操作都得到正确的结果。

同步: 多个任务之间有先后顺序执行,一个执行完下个才能执行。执行完代码后,原地等待,直至出现结果

**异步:**多个任务之间没有先后顺序,可以同时执行有时候一个任务可能要在必要的时候获取另一个 同时执行的任务的结果,这个就叫回调!执行完代码后,不等待,继续执行其他事务(常与回调机制关联)

**阻塞:**如果卡住了调用者,调用者不能继续往下执行,就是说调用者阻塞了。cpu在遇到I/O操作,进入阻塞状态,cpu切换到其他任务

**非阻塞:**如果不会卡住,可以继续执行,就是说非阻塞的。 同步异步相对于多任务而言,阻塞非阻塞相对于代码执行而言。不会遇到I/O操作,cpu一直处于计算状态

**并行:**同一时刻多个任务同时在运行。

实现并行的库:multiprocessing

**并发:**在同一时间间隔内多个任务都在运行,但是并不会在同一时刻同时运行,存在交替执行的情况。

实现并发的库:threading

网络中常用的I/O操作有(accept,recv,send)

协程

(协程是一种更轻量级的线程)【进程里有线程,线程里有协程】

子程序切换不是线程切换,而是由程序自身控制

没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显

不需要多线程的锁机制,因为只有一个线程,也不存n在同时写变量的冲突,在协程中控制共享资源不加锁

具体的生产环境中,Python项目经常会使用多进程+协程的方式,规避GIL锁的问题,充分利用多核的同时又充分发挥协程高效的特性。

aysncio

协程不是计算机提供 是人为创造的

一个线程在代码块之间切换

协程的实现:

​ greenlet 早期模块

​ yield 关键字

​ asyncio装饰器(py3.4)

​ async,awit关键字(py3.5)[主流]

协程的意义:遇到IO等待时间 利用空闲时间进行其他操作

'''greenlet'''
from greenlet import greenlet


def fun():
    print(1)
    gr2.switch()
    print(2)
    gr2.switch()

def fun2():
    print(3)
    gr1.switch()
    print(4)
    gr1.switch()

gr1=greenlet(fun)
gr2=greenlet(fun2)

gr1.switch()

'''yield'''
def func1():
    yield 1
    yield from func2()
    yield 2

def func2():
    yield 3
    yield 4


f1=func1()
for item in f1:
    print(item)
    
'''asyncio装饰器'''    
![image-20211008133227942](C:\Users\JHC\AppData\Roaming\Typora\typora-user-images\image-20211008133227942.png)

'''async awit'''

import asyncio

async def func():
    print(1)
    await asyncio.sleep(2)
    print(2)
async def func2():
    print(3)
    await asyncio.sleep(2)
    print(4)

task=[
    asyncio.ensure_future(func()),
    asyncio.ensure_future(func2())
]
loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yN6ifJlI-1636974873269)(C:\Users\JHC\AppData\Roaming\Typora\typora-user-images\image-20211008133227942.png)]

异步编程

事件循环

死循环 检测并且执行某些代码

垃圾回收机制

引用计数:

创建一次,调用一次,引用计数降为0时自动进行垃圾回收

分代技术:

python中默认定义了三代对象集合,索引越大,对象存活时间越长;python中使用了某些启发式算法来加速垃圾回收(越晚创建的对象越早被回收)

内存池:

  1. Python 的内存机制呈现金字塔形状,-1,-2层主要有操作系统进行操作;

  2. 第0 层是C 中的malloc,free 等内存分配和释放函数进行操作;

  3. 第1 层和第2 层是内存池,有Python 的接口函数PyMem_Malloc 函数实现,当对象小于256K 时有该层直接分配内存;

  4. 第3 层是最上层,也就是我们对Python 对象的直接操作;Python 在运行期间会大量地执行malloc 和free 的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python 的执行效率。为了加速Python 的执行效率,Python 引入了一个内存池机制,用于管理对小块内存的申请和释放。

    Python 内部默认的小块内存与大块内存的分界点定在256 个字节,当申请的内存小于256 字节时,PyObject_Malloc 会在内存池中申请内存;当申请的内存大于256 字节时,PyObject_Malloc 的行为将蜕化为malloc 的行为。当然,通过修改Python 源代码,我们可以改变这个默认值,从而改变Python 的默认内存管理行为。

内存泄漏 ,如何避免 ?

由于疏忽或者错误造成程序未能释放已经不再使用的内存的情况

有del()函数的对象间的循环引用是导致内存泄漏的主凶

不使用一个对象时,使用 del object 来删除对象的引用计数就可以有效的防止内存的泄露问题,可以通过python 的gc扩展模块来查看不能回收的对象的详细信息

可以通过 sys.getrefcount(obj)来获取对象的引用计数,并且根据返回值是否为0来判断是否内存泄漏

如何在python中管理内存

python中使用一个私有堆内存空间来防止所有的对象和数据结构,我们无法直接访问它。由解释器来管理它。不过使用一些核心的API我们可以访问一些Python内存管理工具控制内存的分配

调优手段

手动垃圾回收

调高垃圾回收阈值

避免循环引用:手动解循环引用和使用弱引用

迭代器、生成器、装饰

迭代器是一个可以记住遍历位置的对象,迭代器只能往前,不会后退

迭代器基本方法:iter() next()

字符串,元组,列表 ,字典 对象都可用于创建迭代器,通常使用for循环进行迭代

生成器 yield()

生成器是一个返回迭代器的函数,只能用于迭代操作,简单理解 生成器就是一个迭代器 在调用生成器过程中,每次遇到yield()会暂停并且保存当前所有的运行信息,返回yield的值,并且在下一次执行next()时从当前位置继续执行

调用一个生成器对象,返回一个迭代器对象

区别:生成器能做到迭代器能做的所有事,而且因为自动创建了iter()和next()方法,生成器显得特别简洁,而且

生成器也是高效的,使用生成器表达式取代列表解析可以同时节省内存。除了创建和保存程序状态的自动方法,当生成器终结时,还会自动抛StopIteration 异常。

装饰器本质上是一个Python函数,它可以让已有的函数不做任何改动的情况下增加功能。非常适合有切面需求的场景,比如权限校验,日志记录和性能测试等等。如果你想要执行某个函数前记录日志或者记录时间来统计性能,又不想改动这个函数,就可以通过装饰器来实现。

'''时间装饰器'''
import time

def add_time(func):
    def wrapper(*args,**kwargs):
        start = time.time()
        func(*args,**kwargs)
        end = time.time()

        print("time",end-start)

    return wrapper

@add_time
def my_count():
    s = 0
    for i in range(1000001):
        s += i
    print(s)

# 执行函数
my_count()

read 、readline 、readlines 、xreadlines?

read 读取整个文件

readline 读取下一行,使用生成器方法

readlines 读取整个文件到一个迭代器以供我们遍历

xreadlines()返回一个生成器,来循环操作文件的每一行

函数调用的时候参数的传递方式是 值传递还是引用传递?

不可变参数用值传递

像整数和字符串这样的不可变对象 ,是通过拷贝进行传递的,因为无论如何都不可能在原处改变不可变对象

可变参数是引用传递

像列表,字典这样的对象是通过引用传递,和c语言里边的指针传递数组很类似,可变对象能在函数内部改变

为什么函数 名字可以当作参数使用?

在python中一切皆是对象 函数名是函数在内存中的空间,也是一个对象

请你说说python传参传引用

python 的函数传递方式使用的是引用的方式,就是将实参的地址传递给形参,执行期间实参和形参公用相同的内存单元,被调用的函数对于实形参的任何操作都等同于对实参的操作,所以实参会随着形参的变化而变化

递归函数终止条件?

判断递归次数是否达到某一限定值

判断运算结果是否达到某一范围 根据设计的目的来进行选择

回调函数是如何进行通信的?

把函数地址作为参数传递给另一个函数,将真个函数当作一个对象,赋值给调用的函数

python 的僵尸进程

僵尸进程:子进程结束后父进程并未结束,此时子进程占用的资源(打开的文件,占用的内存)会被cpu回收,但是子进程的信息(进程号PID,运行时间,退出状态)会被保留,子进程变成僵尸进程
僵尸进程的危害:当僵尸进程大量堆积的时候会占用大量的PID号,但是进程号有限,大量的堆积PID号会影响新的子进程生成

python2和python3的区别

python3中的print 使用()

python2中使用ascii编码,python3中使用utf-8编码

pytohn2中使用raw_input() python3中使用input()

python2中rang(1,10)返回列表 python3中返回迭代器

Python 2有为非浮点数准备的int和long类型。int类型的最大值不能超过sys.maxint,而且这个最大值是平台相关的,可以通过在数字的末尾附上一个L来定义长整型,显然,它比int类型表示的数字范围更大。在Python 3里,只有一种整数类型int,大多数情况下,它很像Python 2里的长整型。
由于已经不存在两种类型的整数,所以就没有必要使用特殊的语法去区别他们。

python 的上下文管理器

with open as f: 在内部已经实现了
1. enter
2. exit
这两个方法实现上下文管理器
上下文管理器的优点:
1. 提高代码复用率
2. 提高代码优雅度
3. 提升代码可读性

python 内置数据类型(全部都是引用传递) ?

布尔

数字

字符串

元组

集合

列表

字典

基本数据类型 数值传递的过程 严格来说python中没有数值传递

引用数据类型(内存空间的传递)

除法的结果是float类型

复数 complex()

字典的遍历

  1. for key,value in dict.items()

  2. for key in dict.keys()

  3. for value in dict.values()

输出内建方法?

print(dir(‘a’))

阶乘计算

img

单例模式

'''使用__new__方法'''
class A(object):
	_instance = None
    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = object.__new__(cls)
            return cls._instance
        else:
            return cls._instance
'''使用模块'''
class Singleton(object):
	def foo(self):
        pass
    
singleton = Singleton()

#将上面的代码保存在文件mysingleton.py中,要使用时,直接在其他文件中导入词文件中的对象,这个对象就是单例模式的对象
'''使用装饰器'''
def Singleton(cls):
    _instance = {}
    def _singleton(*args, **kwargs):
        if cls not in _instance:
        	_instance[cls] = cls(*args, **kwargs)
        return _instance[cls]
    return _singleton
@Singleton
class A(object):
    a = 1
    def __init__(self, x=0):
        self.x = x
        
a1 = A(2)
a1 = A(3)
'''
应用场景:
	(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如日志文件,应用配置。
	(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。
	1.网站的计数器
    2.应用配置
    3.多线程池
    4.数据库配置,数据库连接池
    5.应用程序的日志应用…
'''

面向对象编程?

面向对象是一种基于结构分析的、以数据为中心的程序设计思想。在面向对象语言中有一个有很重要东西,叫做类。

面向对象有三大特性:封装、继承、多态。

封装:将某些内容先封装到一个地方,等需要的时候再去调用

继承:即攀升类(子类)可以继承基类(父类)的方法,我们可以将多个类共有的方法提取到父类中,这样子类仅需要继承父类而不必实现每个方法

多继承

​ 在python中 类可以继承多个类,在继承多个类时,它对类中的函数查找有两种当时,他对类中的函数查找有两种方式

深度优先:类是经典类hi,多继承的情况下,会按照深度有限的方式查找

​ **广度优先:**类是新式类,多继承的情况下,会按照广度优先的方式查找

​ (在python3中)都默认是广度优先,但还是可以了解一下两个的区别,

​ 新式类:当前类或者基类继承了object类 就叫新式类,否则就是经典

**多态:**不同的子类对象调用相同的父类方法,产生不同执行效果,可以增加代码的外部调用灵活度。父类变量能够引用子类对象,当子类中有重写父类父类方法,调用的将是子类对象

正则表达式

match() 只有0位置 匹配成功才有返回

search() 扫描整个字符串进行匹配

贪婪模式、非贪婪模式?

贪婪模式:<.>是贪婪匹配,会从第一个“<”开始匹配,直到最后一个“>”中间所有的字符都会匹配到,中间可能会包含“<>”

非贪婪模式*:<.*?>是非贪婪匹配,从第一个“<”开始往后,遇到的第一个“>”:结束匹配,这中间的字符串都会匹配到,但是不会有“<>”

非贪婪模式==贪婪模式后+?

img

算法时间复杂度

img

Mongodb

Mongodb id 由12个字节组成

4字节 自Unix纪元以来的秒数

5字节 随机值

3字节 计数器 从随机位置开始

Mongodb 相对于 RDBMS(关系数据库管理系统) 的优势

无固定结构 - MongoDB 是一个文档数据库,一个集合中可以包含不同的文档。文档的字段数、内容和大小都可以不同

单个对象的结构是清晰的

没有复杂的表连接

查询功能强大

已于扩展、调优

应用程序对象与数据库对象天然对应

使用内存存储工作集,可以更快的访问数据

为什么使用mongodb ?

面向文档的数据库

任意字段的索引

复制和高可用性

自动分片

丰富的查询

就地更新快

Mongodb的专业支持

哪些场景下使用mongodb ?

大数据

内存管理和交付

移动应用/社交应用

用户数据管理

数据中心

use 数据库名
show dbs
db  检查当前数据库
show collections
db.dropDatabase() 	删除数据库
db.createCollection(name,options)	创建集合
db.collectionname.drop()	删除集合 返回true/false
插入数据
db.collectionname.insertone({'key','value'})
db.collectionname.insertmany([{'key','value},{'key','value'}……])	
db.collectionname.save()	指定id 若不指定id与insert相同

查询数据
db.collectionname.find().pretty()
db.collectionname.findone().pretty()

查询符合条件的数据 _id字段不显示
db.collectionname.find({ :''},{_id:0})

只显示两个文档
db.collectionname.find({ :''},{_id:0}).limit(2)

跳过文档数 跳过两个 从第三个开始 skip()默认值为0
db.collectionname.find({ :''},{_id:0}).skip(2)
排序
db.collectionname.find({ :''},{_id:0})。sort({ :''})

更新数据
db.collectionname.update({ :''}),{$set:{ :''}}
db.COLLECTION_NAME.save({_id:ObjectId(), NEW_DATA})

删除符合条件的所有文档
db.collectionname.remove({ :''})
删一条
db.collectionname.remove({ :''},1)
删除全部文档
db.collectionname.remove()


小于:$lt
小于等于:$lte
大于:$gt
大于等于:$gte
不等于:$ne



索引可以让查询更快。如果没有索引,查询文档时时,MongoDB必须扫描集合的每个文档。这种扫描效率非常低,MongoDB需要处理大量数据。
db.collectionname.ensureIndex({ :1})	升序创建索引
db.collectionname.ensureIndex({ :-1})	降序创建索引

聚合
aggregate()

mongodb 支持的数据类型

string 必须是utf8编码格式

integer 正数可以是32位或64位,取决于服务器

boolean

double 双精度 存储浮点数据

min/max keys 此类型用于将值与最低和最高的BSON元素进行比较

arrays 将数组、列表、多个值存储在一个键中

timestamp 时间戳 记录文档合适被修改或创建

object 用于嵌入文档

null 存储null值

symbol 通常用于某些特定符号的语言

date 以UNIX时间格式存储当前日期或时间

objectid 存储文档的id

binary data 存储二进制数据

code 将javascript代码存储到文档中

regular expression 存储正则表达式

linux

linux 定时任务设置

crontab命令用于设置周期性被执行的指令

crontab -l 查看定时任务

Redis

开源 使用C语言编写 支持网络交互 可基于内存也可基于持久化的Key-Values数据库

redis-server.exe	启动服务
redis-cli.exe	连接redis redis-cli --raw	可解析中文
redis-cli shutdown/kill redis-pid	停止redis
redis是一种高级的key-value存储系统 支持五种数据类型
	1. 字符串
	2. 字符串列表
	3. 字符串集合
	4. 有序字符串集合
	5. 哈希
列表
lpush 左添加
rpush 右添加
lrange 指定范围添加元素
lrange myset 0 -1 列出列表所有元素

redis中的集合是一种无序的集合,集合中的元素没有先后顺序
sadd myset 'one' 	向集合中添加元素
smembers myset 	列出myset中的所有元素
sismember myset 'one' 	判断one是否在myset集合中
sunion myset yourset	 求两个集合的并集



DDL(data definition languages)语句:即数据库定义语句,用来创建数据库中的表、索引、视图、存储过程、触发器等,常用的语句关键字有:create,alter,drop,truncate,comment,rename。

DML(data manipulation language)语句:即数据操纵语句,用来查询、添加、更新、删除等,常用的语句关键字有:select,insert,update,delete,merge,call,explain plan,lock table,包括通用性的增删改查。

DCL(data control language)语句:即数据控制语句,用于授权/撤销数据库及其字段的权限(常用的语句关键字有:grant,revoke。

TCL(transaction control language)语句:事务控制语句,用于控制事务,常用的语句关键字有:commit,rollback,savepoint,set transaction。


1. mysql中的锁?
	1)表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突概率高,并发度最低
	2)行级锁:开销大,加锁慢;会出现死锁,锁定粒度最小,发生锁冲突概率最低,并发度最高
	3)页面锁:开销和加锁时间介于中间,会出现死锁;锁定粒度介于中间,并发度一般
2. mysql中不同的表格?
	MyISAM
	Heap
	Merge
	INNODB
	ISAM
3.mysql中MyISAM和INNODB的区别?
	MyISAM 不支持事务,但是每次查询都是原子的;支持表级锁,,每次操作都是对整个表加锁
	存储表的总行数
	一个MyISAM表由三个文件:索引文件、表结构文件、数据文件
	采用非聚类索引,索引文件指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证一致性
	INNODB 支持ACID事务,支持事务的四种隔离级别;支持行级锁和外键约束,支持写并发
	不存储总行数
	一个INNODB引擎引擎存储在一个文件空间受操作系统文件大小限制
	主索引采用聚类索引,辅索引的数据域存储主键的值,因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引,最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整
4. mysql隔离级别?
	读未提交	脏读 不可重复读 幻读
	读已提交	不可重复读 幻读
	可重复读(默认)	幻读
	串行化 
不可重复读重点在于update和delete,而幻读的重点在于insert
	
5. 主键和候选键的区别?
	表格的每一行都由主键唯一标识,一个表只有一个主键
	主键也是候选键 候选键可以被指定为主键,并且可以用于任何外键的引用
6. myisamchk用看做什么?
	以上所MyISAM表 减少磁盘和内存的使用
7. MyISAM Static 和MyISAM Dynamic的区别?
	MyISAM Static 上所有字段有固定长度,动态的MyISAM表具有TEXT(比较排序时 不区分大小写的BLOB字段),BLOB(二进制对象,容纳可变数量的数据)等字段,以适应不同长度的数据类型
	MyISAM Static 在受损情况下更容易恢复
8. 如果一个表中有一列定义为TIMESRAATMP 将会发生什么?
	当行被更改时,时间戳字段将获取当前时间戳
9. 列设置为AUTO INCREMENT时,如果表中达到最大值,会发生什么情况?
	会停止递增,任何进一步的插入都会产生错误,因为密钥被使用
10. 怎样才能找出最后一次插入时分配了哪个自动增量?
	LAST_INSERT_ID将返回由Auto_increment分配的最后一个值,并且不需要指定表名称。
11. 如何在Unix和Mysql时间戳之间进行转换?
	UNIX_TIMESTAMP是从Mysql时间戳转换为Unix时间戳的命令
	FROM_UNIXTIME是从Unix时间戳转换为Mysql时间戳的命令
12. mysql_fetch_array和mysql_fetch_object的区别是什么?
	mysql_fetch_array() – 将结果行作为关联数组或来自数据库的常规数组返回。
	mysql_fetch_object – 从数据库返回结果行作为对象
13. MyISAM表格将在哪里存储,并且还提供其存储格式?
	每个MyISAM表格以三种格式存储在磁盘上:

		·“.frm”文件存储表定义

		·数据文件具有“.MYD”(MYData)扩展名

		索引文件具有“.MYI”(MYIndex)扩展名
14. Mysql如何优化DISTINCT?
	DISTINCT在所有列上转换为GROUP BY,并与ORDER BY子句结合使用。

15. Mysql 中的数据类型?
	数值类型
	日期、时间类型
	字符串类型
16.mysql的索引类型?
	主键索引(聚集索引)(聚簇索引):数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同【聚集索引做查询可以直接获取对应的全部列的数据.所以聚集查询较快】
	唯一索引
	非聚簇索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引,除了聚集索引以外的索引都是非聚集索引,分成(普通索引,唯一索引和全文索引)【非聚集索引查询在索引没覆盖到对应列的时候需要进行二次查询,索引非聚集查询较慢】

解决非聚集索引二次查询问题?
	复合索引(覆盖索引):建立两列以上的索引,即可查询复合索引里的列的数据而不需要进行回表二次查询【要注意使用复合索引需要满足最左侧索引的原则,也就是查询的时候如果where条件里面没有最左边的一到多列,索引就不会起作用.】
	
17.建立索引的原则?

定义主键的数据列一定要建立索引。

定义有外键的数据列一定要建立索引。

对于经常查询的数据列最好建立索引。

对于需要在指定范围内的快速或频繁查询的数据列;

经常用在WHERE子句中的数据列。

经常出现在关键字order by、group by、distinct后面的字段,建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致,否则索引不会被使用。

对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。

对于定义为text、image和bit的数据类型的列不要建立索引。

对于经常存取的列避免建立索引

限制表上的索引数目。对一个存在大量更新操作的表,所建索引的数目一般不要超过3个,最多不要超过5个。索引虽说提高了访问速度,但太多索引会影响数据的更新操作。

对复合索引,按照字段在查询条件中出现的频度建立索引。在复合索引中,记录首先按照第一个字段排序。对于在第一个字段上取值相同的记录,系统再按照第二个字段的取值排序,以此类推。因此只有复合索引的第一个字段出现在查询条件中,该索引才可能被使用,因此将应用频度高的字段,放置在复合索引的前面,会使系统最大可能地使用此索引,发挥索引的作用。

image-20211013110044594

image-20211013105948454

select * from test.salgrade;
select * from test.dept;
select * from test.emp;

use test;
show tables ;

# 擦查看表结构
desc test.dept;
desc test.emp;
desc test.salgrade;


# 查看当前使用的数据库版本
select version();
# 查看当前使用的数据库
show databases ;



# 简单查询语句
desc dept;
select DNAME from dept;
select DNAME,DEPTNO from dept;

# 列起别名
select DNAME as dn from dept;
select DNAME dn from dept;
select DEPTNO 'd n t' from dept;

# 计算年薪 中文别名用单引号括起来
select ENAME '名字',SAL*12 '年薪' from emp;

# 条件查询
select ENAME '名字' ,SAL*12 as '年薪' from emp where sal*12>19200;
# <> = !=
select ENAME,SAL from emp where SAL<>1600;
select ENAME,SAL from emp where SAL != 1600;
# between and  必须左小右大 闭区间
select ENAME,SAL from emp where SAL<=1600 and SAL>=800;
select ENAME,SAL from emp where SAL between 800 and 1500;
# 查询空补助 用is 衡量 null
select ENAME,COMM from emp where COMM is not NULL;
select ENAME,COMM from emp where COMM is NULL;
# 工作岗位是manager 且工资大于2500
select JOB from emp;
select EMPNO,JOB,ENAME,SAL from emp where JOB='MANAGER' and SAL>2500;
# 查工作岗位是 manager 和 salesman 的员工信息
select * from emp where JOB='manager' or JOB='salesman' and COMM is null;
# 查工资大于2500 且部门编号为 10或20 的员工
# and和偶or在一块将or括起来  and的优先级较高
desc emp;
select DEPTNO,ENAME,SAL from emp where SAL>2500 and (DEPTNO=10 or DEPTNO=20);
# 查询工作岗位是manager和salesman的员工
select JOB from emp;
select ENAME,JOB from emp where JOB='MANAGER' or JOB='SALESMAN';
select ENAME,JOB from emp where JOB in('MANAGER','SALESMAN') order by JOB;
# 查工资800和工资5000的员工信息
select EMPNO,ENAME,SAL,DEPTNO from emp where SAL=800 or SAL=5000;
select EMPNO,ENAME,SAL,DEPTNO from emp where SAL in(800,5000);
# 找出名字以T结尾的员工信息
select ENAME,EMPNO from emp where ENAME like '%T';
select ENAME,EMPNO from emp where ENAME like '%t%';
select ENAME,EMPNO from emp where ENAME like 'T%';
# 查询工资 默认升序 desc降序
select ENAME,SAL from emp order by SAL desc;
# 多字段排序
select ENAME,SAL from emp order by SAL,ENAME;

select ENAME,SAL from emp where SAL between 1250 and 3000 order by SAL;

# 数据处理函数    单行处理函数
#               多行处理函数    多个输入对应一个输出
# 常见单行处理函数
select lower(ENAME)  smallename from emp;
select upper(ENAME) from emp;
# 从1开始截取3个长度
select substr(ENAME,1,3) from emp;
# 名字首字母大写
select concat(upper(substr(ENAME,1,1)),lower(substr(ENAME,2,length(ENAME)-1))) from emp;

select concat(upper(substr(ENAME,1,1)),lower(substr(ENAME,2,length(ENAME)-1))) from emp;

select concat(ENAME,' ',JOB,' ',SAL) from emp;

select * from emp;
# 删首空格 leading
SELECT TRIM(LEADING FROM '    MySQL TRIM Function   ');
# 删首尾空格
select trim('    MySQL TRIM Function   ');
# 删尾空格 trailing
SELECT TRIM(TRAILING FROM '    MySQL TRIM Function   ');


select 2100 as num from dept;
# 四舍五入 第二个参数是保留的有效数字位数
select round(1234.467,4)  result from emp;
select round(1234.567,-2)  result2 from emp;
# 随机数
select rand(rand()*100) from dept;
# null 参与运算 结果为null
select EMPNO,sal+COMM salcomm from emp;
# 查询年薪(月薪+补助)
select EMPNO,ENAME,(SAL+ifnull(COMM,0))*12 yearsal from emp;
# 当工作岗位是manager时工资上调10% 当工作岗位是salesman时工资上调50% 工资结果四舍五入 case when then when then else end
select ENAME,JOB,round((case JOB when 'manager' then SAL*1.1 when 'salesman' then SAL*1.5 else SAL end ),0) salresult from emp;



# 分组函数(多行处理函数)count\sum\avg\max\min 分组函数自动忽略null
select max(SAL) from emp;
select round(avg(SAL),0) from emp;
select min(SAL) from emp;
select count(*) from emp;


select ENAME,JOB,sum(SAL) from emp group by JOB;
select ENAME,JOB,sum(SAL) from emp group by DEPTNO;
# where后不能使用分组函数
select DEPTNO,JOB,max(SAL) from emp group by DEPTNO, JOB;
select * from emp;
select DEPTNO,max(SAL) from emp group by DEPTNO having max(SAL)>3000;
select DEPTNO,SAL from emp where SAL>3000 group by DEPTNO;
select DEPTNO,SAL from emp where SAL>2500 group by DEPTNO;

select SAL,DEPTNO,JOB from emp;
select JOB,avg(SAL) from emp where JOB<>'MANAGER' group by JOB having avg(SAL)>1500 order by avg(SAL) desc ;
# c
select JOB,avg(SAL) avgsal from emp where JOB!='manager' group by JOB having avgsal>1500 order by avgsal desc ;


mysql索引

索引能够快速查询的原因

使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据。

索引类型分类

普通索引:加快查询速度

唯一索引:加快查询速度,并且可以限制列值的唯一性,允许为空; 唯一索引包括联合唯一索引,多列形成的唯一索引,这些列可以唯一确定一条表记录,可以为空

全文索引: 主要针对文本的内容进行分词,加快查询速度

联合索引: 多列组成的索引,查询效率提升高于多个单列索引合并的效率

主键索引: 主键唯一性,加快查询速度,不能为空

索引结构分类

B-tree索引:使用B-tree数据结构来存储数据;每个叶子节点都会包含下一个节点的指针,非常方便查询数据;B-tree 适用于全键值,键值范围,或者前缀查找

哈希索引:哈希索引基于哈希表实现,对于每一行数据,存储引擎会对所有的索引列计算一个哈希码,然后存储引擎会基于这个哈希码来查找数据,小编感觉有点像HashMap 中槽的查询过程

全文索引: 全文索引在几种索引结构类型中比较特殊,他查找的是文本中关键词

建议不要使用索引的几种情况:

区分度不是很大的字段,例如 性别 sex

频繁更新的字段

字符串类型的字段 或者 文本类型的字段

不在where列中出现的索引

索引失效的几种情况:

查询列中有函数计算

查询列中有模糊查询,“%cloum”,可以使用"cloum%" 代替,如果要使用"%column%",那么select 列中是索引列

如果查询条件中有or, 索引会失效,除非所有条件都加上索引

使用不等于(!= 或者 <>)

is null 或者 is not null

字符串不加引号,会导致索引失效

最左原则,联合索引中会遵循最左原则,即如果要使用联合索引,那么前面的索引列一定要包含

explain 分析查询sql

python 打包exe

pyinstaller -F -w -i .py路径

pipreqs . encoding = utf8 --force

-F : 可执行程序

-w : 无黑窗口

-i : 图标

python生成requirements.txt 依赖

生成 :pip freeze > requirements.txt

安装 : pip install -r requirements.txt

is 和 ==的区别 (身份运算符)?

is 内存地址相同 值也必相同

== 值相同

python 字符串驻留机制:当字符串较小时,为了提高系统性能,python 会保留一个它的副本,当创建新的字符串时,直接指向该副本即可

 # 身份运算符 进行完全相等的判断   唯一与底层交互
 # 通过id()获取变量在内存的地址空间
 # 整形和浮点型进行比较时,整型会自动转换成浮点型进行比较
    a = 2
    b = 2.0
    print(id(a),id(b))
    print(a==b)
    print(a is b)
    print(id(a)==id(b))

关系型数据库和非关系型数据库的区别?

数据存储方式不同

关系型数据库以表格方式存储数据(行列)

非关系型数据库数据存储在数据集中【文档、键值对、图结构】

扩展方式不同

SQL数据库是纵向扩展,提高处理能力,使用速度更快速的计算机

而非关系型数据存储天然就是分布式的,NoSQL数据库的扩展可以通过给资源池添加更多普通的数据库服务器(节点)来分担负载

对事务性的支持不同

SQL数据库支持对事务原子性细粒度控制,并且易于回滚事务

虽然NoSQL数据库也可以使用事务操作,但稳定性方面没法和关系型数据库比较,所以它们真正闪亮的价值是在操作的扩展性和大数据量处理方面

解释型语言和编译型语言 ?

解释型语言编写的程序不需要编译,在执行的时候,专门有一个解释器能够将VB语言翻译成机器语言,每个语句都是执行的时候才翻译。这样解释型语言每执行一次就要翻译一次,效率比较低。

用编译型语言写的程序执行之前,需要一个专门的编译过程,通过编译系统,把源高级程序编译成为机器语言文件,翻译只做了一次,运行时不需要翻译,所以编译型语言的程序执行效率高,但也不能一概而论,部分解释型语言的解释器通过在运行时动态优化代码,甚至能够使解释型语言的性能超过编译型语言。

位和字节的关系?

bit就是位,也叫比特位,是计算机表示数据最小的单位

byte就是字节

1byte=8bit

1byte就是1B

一个字符=2字节

1KB=1024B

字节就是Byte,也是B

1KB=1024B

1B= 8b

字节码和机器码的区别?

机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU`可直接解读的数据。

通常意义上来理解的话,机器码就是计算机可以直接执行,并且执行速度最快的代码。

用机器语言编写程序,编程人员要首先熟记所用计算机的全部指令代码和代码的涵义。
手编程序时,程序员得自己处理每条指令和每一数据的存储分配和输入输出,还得记住编程过程中每步所使用的工作单元处在何种状态。
这是一件十分繁琐的工作,编写程序花费的时间往往是实际运行时间的几十倍或几百倍。
而且,编出的程序全是些0和1的指令代码,直观性差,还容易出错。
现在,除了计算机生产厂家的专业人员外,绝大多数的程序员已经不再去学习机器语言了。

机器语言是微处理器理解和使用的,用于控制它的操作二进制代码。

8086到Pentium的机器语言指令长度可以从1字节到13字节。

尽管机器语言好像是很复杂的,然而它是有规律的。

存在着多至100000种机器语言的指令。这意味着不能把这些种类全部列出来

总结:机器码是电脑CPU直接读取运行的机器指令,运行速度最快,但是非常晦涩难懂,也比较难编写,一般从业人员接触不到。

字节码(Bytecode)是一种包含执行程序、由一序列 op 代码/数据对 组成的二进制文件。字节码是一种中间码,它比机器码更抽象,需要直译器转译后才能成为机器码的中间代码。

通常情况下它是已经经过编译,但与特定机器码无关。字节码通常不像源码一样可以让人阅读,而是编码后的数值常量、引用、指令等构成的序列。

字节码主要为了实现特定软件运行和软件环境、与硬件环境无关。字节码的实现方式是通过编译器和虚拟机器。编译器将源码编译成字节码,特定平台上的虚拟机器将字节码转译为可以直接执行的指令。字节码的典型应用为Java bytecode。

字节码在运行时通过JVM(JAVA虚拟机)做一次转换生成机器指令,因此能够更好的跨平台运行。

总结:字节码是一种中间状态(中间码)的二进制代码(文件)。需要直译器转译后才能成为机器码。

列表去重

my_list = [1,1,2,2,3,3,5,6,7,88]
my_set = set(my_list)
my_list = [x for x in my_set]
my_list
'''循环判断去重'''
ids = [1,1,2,2,3,3,5,6,7,88]
news_ids = []
for id in ids:
    if id not in news_ids:
        news_ids.append(id)
print(news_ids)
'''字典的fromkeys方法实现'''
my_list=[1,1,2,2,3,3,5,6,7,88]
d = {}.fromkeys(my_list)
print(d.keys()) 

统计如下list单词及其出现的次数。

'''a=['apple', 'banana', 'apple', 'tomato', 'orange', 'apple', 'banana', 'watermeton']'''

# 1. 利用字典。

a = ['apple', 'banana', 'apple', 'tomato', 'orange', 'apple', 'banana', 'watermeton']
dic = {}
for key in a:
    dic[key] = dic.get(key, 0) + 1
print(dic)

# 2. 利用python的collections包。
from collections import Counter

a = ['apple', 'banana', 'apple', 'tomato', 'orange', 'apple', 'banana', 'watermeton']
d = Counter(a)
print(d)

<class 'collections.Counter'>

给列表中的字典排序

alist = [{"name": "a", "age": 20}, {"name": "b", "age": 30}, {"name": "c", "age": 25}]
alist.sort(key=lambda x: x['age'])
print(alist)

在Python中读取大文件

'''利用生成器generator'''
def read_in_block(file_path):    
    BLOCK_SIZE = 1024    
    with open(file_path, "r") as f:        
        while True:            
            block = f.read(BLOCK_SIZE)  # 每次读取固定长度到内存缓冲区            
            if block:                
                yield block            
            else:                
                return  # 如果读取到文件末尾,则退出  def test3():    
            file_path = "/tmp/test.log"    
            for block in read_in_block(file_path):        
                print block        
'''迭代器进行迭代遍历:for line in file '''
def test4():    
    with open("/tmp/test.log") as f:        
        for line in f:            
            print line 

简要描述python中 单引号、双引号、三引号的区别。

单引号和双引号在使用时基本上没有什么区别,当字符串中有单引号时,最好在外面使用双引号;当有双引号时,最好在外面使用单引号。

三引号一般不常用,除了用来做注释之外,还可以用来打印多行字符串。特殊用途,是可以打印多行字符串。

\ 续行符

import string
    
print(string.ascii_uppercase)
print(string.ascii_lowercase)
print(string.ascii_letters)

'''
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
'''

进制转换

print(bin(2))   # 十转二
print(oct(2))   # 十转八
print(hex(2))   # 十转十六
# 转十
print(int(0x2)) 
print(int(0o2))
print(int(0b10))

如何在一个function里设置一个全局的变量。

全局变量是指定义在函数外部的变量。全局变量的作用域为全局。

局部变量是指定义在函数内部的变量。局部变量的作用域为函数内,出了函数就无效了。

这里举个例子,如果把函数比作国家,那么全局就是全球,全局变量好比是阿拉伯数字,每个国家都认识。

所以,根据定义可以知道,在函数内部是无法定义一个全局变量的,只能做到修改已经定义的全局变量。

Python的最大递归层数

Python的最大递归层数是可以设置的,默认的在window上的最大递归层数是 998

import sys
sys.setrecursionlimit(100000)

def foo(n):
    print(n)
    n += 1
    foo(n)

if __name__ == '__main__':
    foo(1)

xrange和range的区别

python2中 xrange 用法与 range 完全相同,所不同的是生成的不是一个list对象,而是一个生成器。

布尔值为False的常见值

None、“”、0、[]、()、{}

pass的作用

pass是空语句占位符,是为了保持程序结构的完整性。

什么是断言?应用场景 ?

Python的assert是用来检查一个条件,如果它为真,就不做任何事。如果它为假,则会抛出AssertError并且包含错误信息。

AssertError不是在测试参数时应该抛出的错误

断言应该用于

防御型的编程
  运行时检查程序逻辑
  检查约定
  程序常量
  检查文档

确保代码的正确性

简述OSI七层网络模型

OSI的概念

Open System Interconnect开放系统互连参考模型,是由ISO(国际标准化组织)定义的。它是个灵活的、稳健的和可互操作的模型,并不是协议,是用来了解和设计网络体系结构的。

OSI模型的目的

规范不同系统的互联标准,使两个不同的系统能够较容易的通信,而不需要改变底层的硬件或软件的逻辑。

OSI分为哪七层?

OSI把网络按照层次分为七层,由下到上分别为物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

img

应用层

为应用软件提供接口,使应用程序能够使用网络服务

常见的应用层协议:

http(80)、https(443)、 dns(53)、ftp(20/21)、smtp(25)、pop3(110)、telnet(23)

表示层

数据的解码和编码、加密和解密、压缩和解压缩

图片:jpg、gif……

音频:mp3、wma、aac……

视频:mp4、avi……

会话层

在设备或节点之间提供会话控制,协调通信过程,并提供3种不同的方式来组织它们之间的通信,单工、半双工、全双工

单工:BB机,只能收不能发。

半双工:对讲机,收的时候不能发,发的时候不能收。

全双工:电话,手机,能同时收发。

传输层(TCP/UDP)

负责建立端到端的连接,保证报文在端到端之间的传输。

服务点编址、分段与重组、连接控制、流量控制、差错控制。

网络层(IP) 代表:路由器

为网络设备提供逻辑地址

进行路由选择、维护路由表,负责将分组数据从源端传输到目的端

数据链路层(MAC) 代表:交换机

在不可靠的物理链路上,提供可靠的数据传输服务,把帧从一跳(结点)移动到另一跳(结点)。

组帧、物理编址、流量控制、差错控制、接入控制

物理层 代表:集线器

负责把逐个的比特从一跳(结点)移动到另一跳(结点)。

定义接口和媒体的物理特性(线序、电压、电流)

定义比特的表示、数据传输速率、信号的传输模式

定义网络物理拓扑(网状、星型、环型、总线型等拓扑)

OSI参考模型的特点及各层之间的联系

重要特点:

1、OSI模型每层都有自己的功能集;

2、层与层之间相互独立又相互依靠;

3、上层依赖于下层,下层为上层提供服务

各层之间的联系:

img

TCP 三次握手 四次挥手

七层osi网络结构

TCP传输的可靠性主要靠以下手段来保证传输

ACK确认机制: 简单的说就是发送随机生成一个数字,接收端在确认收到数据,提取随机数并加1,返回发送端,告知确认收到数据包,同时也保证数据接收的唯一性

超时重传:发送方在一定时间内未收到对方的回传的ack确认码,则将数据重新发送,保证数据传输的一致性

滑动窗口

流量控制

img

基于tcp 协议的套接字通信流程

1). 服务器先用 socket 函数来建立一个套接字,用这个套接字完成通信的监听。

2). 用 bind 函数来绑定一个端口号和 IP 地址。因为本地计算机可能有多个网址和 IP,每一个 IP 和端口有多个端口。需要指定一个 IP 和端口进行监听。

3). 服务器调用 listen 函数,使服务器的这个端口和 IP 处于监听状态,等待客户机的连接。

4). 客户机用 socket 函数建立一个套接字,设定远程 IP 和端口。

5). 客户机调用 connect 函数连接远程计算机指定的端口。

6). 服务器用 accept 函数来接受远程计算机的连接,建立起与客户机之间的通信。

7). 建立连接以后,客户机用 write 函数向 socket 中写入数据。也可以用 read 函数读取服务器发送来的数据。

8). 服务器用 read 函数读取客户机发送来的数据,也可以用 write 函数来发送数据。

9). 完成通信以后,用 close 函数关闭 socket 连接。

路由器和交换机的不同之处有哪些 ?

工作层次不同:

交换机主要工作在数据链路层(第二层)

路由器工作在网络层(第三层)。
转发依据不同:

交换机转发所依据的对象时:MAC地址。(物理地址)

路由转发所依据的对象是:IP地址。(网络地址)
主要功能不同:

交换机主要用于组建局域网,

而路由主要功能是将由交换机组好的局域网相互连接起来,或者接入Internet。

交换机能做的,路由都能做。

交换机不能分割广播域,路由可以。

路由还可以提供防火墙的功能。

路由配置比交换机复杂。
价格不同

交换机是看门大爷,路由是邮差。

Socket网络编程过程 ?

客户端

创建套接字

绑定ip及端口

监听连接请求

accept等待客户请求连接

客户端和服务器端用send和recv 方法传输数据

socket.close() 关闭连接

服务器端

建立socket对象

连接服务器

send recv 通信

关闭连接

C/S 和 B/S 架构

C/S架构是一种比较早的软件架构,主要应用于局域网内。在这之前经历了集中计算模式,随着计算机网络的进步与发展,尤其是可视化工具的应用,出现过两层C/S和三层C/S架构,不过一直很流行也比较经典的是我们所要研究的两层C/S架构

img

粘包

粘包:

在接收数据时,一次性多接收了其它请求发送来的数据(即多包接收)。如,对方第一次发送hello,第二次发送world,在接收时,应该收两次,一次是hello,一次是world,但事实上是一次收到helloworld,一次收到空,这种现象叫粘包。

原因
粘包问题主要还是因为接收方不知道消息之间的界限,不知道一次性提取多少字节的数据所造成的。

什么情况会发生:

1、发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据很小,会合到一起,产生粘包)

2、接收方不及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)

解决方案:

一个思路是发送之前,先打个招呼,告诉对方自己要发送的字节长度,这样对方可以根据长度判断什么时候终止接受。

C/S架构的优点

1**)客户端和服务器直接相连**

a)点对点的模式使得更安全。

b)可以直接操作本地文本,减少获取文本的时间和精力。

c)由于直接相连,减少了通信流量,这对于客户来说可以节约一大笔费用。

d)直接相连,中间没有什么阻隔或岔路,所以响应速度快。当通信量少的时候没什么感觉,但是如果通信量庞大,就不会出现拥堵的现象。

2)客户端可以处理一些逻辑事务

a)充分利用两者的硬件设施,避免资源的浪费。

b)为服务器分担一些逻辑事务,可以进行数据处理和数据存储。可以处理复杂的事务流程。

c)客户端有一套完整应用程序,在出错提示、在线帮助等方面都有强大的功能,并且可以在子程序间自由切换。

3) 客户端操作界面

a)可以提高客户的视觉体验,满足客户需求。

b)客户端操作界面可以随意排列,充分满足客户的需要,展现特点与个性。

C/S架构的缺点

1)客户端

a)只能处理一些功能单一的多系统。

b)C/S架构适用于局域网,对网速的要求比较高。

c)由于需要安装客户端,安装部署困难,所以不易扩展。

d)若客户端使用的系统不同,就要针对这些系统分别编写程序。

e)客户端界面缺乏通用性,且当业务更改时就需要更改界面,重新编写。

f)客户端需要专门的客户端程序,比较麻烦,针对点多面广且不具备网络条件的用户群体,不能够实现快速部署安装和配置。

2)服务器

a)用户数增多会出现通信拥堵,服务器响应速度慢等情况。

b)当服务器难当大任时,只能将其废弃,使用更强大的服务器。

c)当客户端用户增多时,服务器难以承担重负,是名副其实的“胖”客户端。

d)用户是通过ODBC连接到数据库的,且每个连接到数据库的用户都会保持一个ODBC连接,会一直占用中央服务器的资源,对服务器的要求很高。

3)用户

a)没有安装客户端的外部用户不能访问。

b)只有安装了客户端才能访问服务器,所以用户不能随时随地的访问。

c)用户是通过ODBC连接到数据库的,所以用户数受限,不易扩张。

d)由于针对小范围的客户,所以不能实现真正大范围的信息共享,信息传达和发布。

4)开发成本

a)需要聘用高素质的人员,对其培训,费用高。

b)初次开发就需要配备好客户端,服务器,需要有专业水准的技术人员,所以成本高。

5)后期成本

a)系统升级维护麻烦,需要更改大量程序,投入大量精力和金钱。

b)业务扩展或变更时,需要更改程序,客户端的界面也需要重新更改。

c)初次投入成本后不能一劳永逸,后期需要很多成本,比如服务器的更换,客户端的更变等。

B/S型模式 是C/S架构的一种改进,可以说属于三层C/S架构。主要是利用了不断成熟的WWW浏览器技术,用通用浏览器就实现了原来需要复杂专用软件才能实现的强大功能,并节约了开发成本,是一种全新的软件系统构造技术

img

B/S架构的优点

1)浏览器

a)能面对广大的用户实现信息传播共享。

b)浏览器只处理一些简单的逻辑事务,负担小。

c)页面的更新能实现同步,所有用户都能看到。

d)界面设计开发简单,对程序员的要求较低,不需要大量的培训。

e)业务扩展方便,只需要增加几个业务扩展的页面即可,不需要大量的编程。

f)界面不需要太多的编写,比较通用,更改界面也比较简单,所以几乎不需要维护。

g)由于Web的平台无关性,可以从一台服务器、几个用户的工作组级扩展成为拥有成上万用户的大型系统。

2)服务器

a)数据都集中存放在数据库服务器,所以不存在数据不一致现象。

b)能有效地保护数据平台和管理访问权限,服务器数据库也很安全。

c)在数据库服务器上不一定使用WINDOWS系统,选择更多,成本更少。

d)如果是异地,只需要把服务器连接专网即可,实现远程维护、升级和共享。

e)在JAVA这样的跨平台语言出现之后,B/S架构管理软件更是方便、快捷、高效。

f)数据存放在数据库服务器,客户端并不存放任何业务数据或者数据库连接信息,所以数据比较安全。

g)随着服务器负载的增加,可以平滑地增加服务器的个数并建立集群服务器系统,然后在各个服务器之间做负载均衡。

3)用户

a)B/S建立在广域网上,所需的网速不高。

b)外部的用户也可以对浏览器进行访问。

c)界面人性化,通用化,不需要多少培训就能掌握。

d)不需要安装客户端,只要能连上网,就能随时随地的浏览页面。

e)借助Internet强大的信息发布与信息传送能力可以有效地解决企业内部的大量不规则的信息交流。

f)所有的用户都是通过一个JDBC连接缓冲池连接到数据库的,用户并不保持对数据库的连接,用户数基本上是无限的。

4)成本

a)软件重用性强,节省了大量的成本。

b)不需要安装特殊的软件,客户端几乎零维护。

c)开发简单,升级便捷,人员不需要太多培训,节省了大量的资金。

d)客户端几乎不需要维护,只要盯紧服务器就可以了,所以成本较小。

e)一般只有初期一次性投入成本,有利于软件项目控制和避免IT黑洞

f)建立在广域网之上的, 不必是专门的网络硬件环境,例如电话上网, 租用设备等,成本较小。

B/S架构的缺点

1)客户端

a)面通用化,不突出个性。

b)页面需要不断地动态刷新,尤其是用户增多,网速慢得情况,很费时。

c)由于不需要安装客户端,客户端易扩展,还有就是外部用户也可以访问,所以B/S面对大量的不可知用户。

2)服务器

a)用户增多时,服务器响应速度慢。

b)功能虽然多样化,但是不能专门化,不能实现复杂的功能。

c)服务器承担着重要的责任,数据负荷较重。一旦发生服务器“崩溃”等问题,后果不堪设想。

C/S和B/S的不同点

img

js

js实现浏览器滑动窗口(webdriver)

 for i in range(1,9): #滑动次数
        js = "var q=document.documentElement.scrollTop={}".format(i * 500)  # 滑动距离
        driver.execute_script(js) # 执行滑动
        time.sleep(0.1) # 休眠加载网页信息

数仓

数据仓库(DataWarehouse),一般缩写成DW、DWH。数据仓库是一个面向主题的(Subject Oriented)、集成的(Integrate)、相对稳定的(Non-Volatile)、反映历史变化(Time Variant)的数据集合,用于支持管理决策。

数据仓库分层

为什么分层?

说说对数据仓库的理解

数据仓库是面向主题进行组织的,数据是集成的、不可更新的、随时间变化的的。

数据仓库经历了这样三个阶段:简单报表阶段、数据集市阶段、数据仓库阶段。

数据库和数据仓库的区别

数据库:是一种逻辑概念,用来存放数据的仓库,通过数据库软件来实现。数据库由很多表组成,表是二维的,一张表里可以有很多字段。

数据仓库:是数据库概念的升级。从逻辑上理解,数据库和数据仓库没有区别,都是通过数据库软件实现存放数据的地方,但是从数据量来讲数据仓库比数据库更庞大些。数据仓库的主要作用用于数据挖掘、数据分析,辅助领导来做决策的。

软件工程一般流程

软件工程中用到的图

流程图,数据流图,E-R图,活动图,用例图

类属性改变了,实例属性会跟着改变

因为我们的实例对象就是根据类来复制出来的,类属性改变了,实例对象的属性也会跟着改变

不管实例对象怎么修改属性值,对类的属性还是没有影响的

https://www.bilibili.com/video/BV1uZ4y1p77F?p=93
业务数据或者数据库连接信息,所以数据比较安全。

g)随着服务器负载的增加,可以平滑地增加服务器的个数并建立集群服务器系统,然后在各个服务器之间做负载均衡。

3)用户

a)B/S建立在广域网上,所需的网速不高。

b)外部的用户也可以对浏览器进行访问。

c)界面人性化,通用化,不需要多少培训就能掌握。

d)不需要安装客户端,只要能连上网,就能随时随地的浏览页面。

e)借助Internet强大的信息发布与信息传送能力可以有效地解决企业内部的大量不规则的信息交流。

f)所有的用户都是通过一个JDBC连接缓冲池连接到数据库的,用户并不保持对数据库的连接,用户数基本上是无限的。

4)成本

a)软件重用性强,节省了大量的成本。

b)不需要安装特殊的软件,客户端几乎零维护。

c)开发简单,升级便捷,人员不需要太多培训,节省了大量的资金。

d)客户端几乎不需要维护,只要盯紧服务器就可以了,所以成本较小。

e)一般只有初期一次性投入成本,有利于软件项目控制和避免IT黑洞

f)建立在广域网之上的, 不必是专门的网络硬件环境,例如电话上网, 租用设备等,成本较小。

B/S架构的缺点

1)客户端

a)面通用化,不突出个性。

b)页面需要不断地动态刷新,尤其是用户增多,网速慢得情况,很费时。

c)由于不需要安装客户端,客户端易扩展,还有就是外部用户也可以访问,所以B/S面对大量的不可知用户。

2)服务器

a)用户增多时,服务器响应速度慢。

b)功能虽然多样化,但是不能专门化,不能实现复杂的功能。

c)服务器承担着重要的责任,数据负荷较重。一旦发生服务器“崩溃”等问题,后果不堪设想。

C/S和B/S的不同点

[外链图片转存中…(img-QsokdC7c-1636974873280)]

js

js实现浏览器滑动窗口(webdriver)

 for i in range(1,9): #滑动次数
        js = "var q=document.documentElement.scrollTop={}".format(i * 500)  # 滑动距离
        driver.execute_script(js) # 执行滑动
        time.sleep(0.1) # 休眠加载网页信息

数仓

数据仓库(DataWarehouse),一般缩写成DW、DWH。数据仓库是一个面向主题的(Subject Oriented)、集成的(Integrate)、相对稳定的(Non-Volatile)、反映历史变化(Time Variant)的数据集合,用于支持管理决策。

数据仓库分层

[外链图片转存中…(img-eWNmj2Cw-1636974873281)]

为什么分层?

[外链图片转存中…(img-dIXiwXyo-1636974873281)]

说说对数据仓库的理解

数据仓库是面向主题进行组织的,数据是集成的、不可更新的、随时间变化的的。

数据仓库经历了这样三个阶段:简单报表阶段、数据集市阶段、数据仓库阶段。

数据库和数据仓库的区别

数据库:是一种逻辑概念,用来存放数据的仓库,通过数据库软件来实现。数据库由很多表组成,表是二维的,一张表里可以有很多字段。

数据仓库:是数据库概念的升级。从逻辑上理解,数据库和数据仓库没有区别,都是通过数据库软件实现存放数据的地方,但是从数据量来讲数据仓库比数据库更庞大些。数据仓库的主要作用用于数据挖掘、数据分析,辅助领导来做决策的。

软件工程一般流程

[外链图片转存中…(img-VttI0GUI-1636974873282)]

软件工程中用到的图

流程图,数据流图,E-R图,活动图,用例图

类属性改变了,实例属性会跟着改变

因为我们的实例对象就是根据类来复制出来的,类属性改变了,实例对象的属性也会跟着改变

不管实例对象怎么修改属性值,对类的属性还是没有影响的

https://www.bilibili.com/video/BV1uZ4y1p77F?p=93

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值