一 基础阶段

1 数据类型:

python数据类型:int/float/str/bool/list/tuple/set/dict

可变类型(可以修改元素):list, dict, set

不可变类型:int, float, bool, str, tuple

2 数据类型常用操作:字符串常用操作 

3 内置模块/函数:

random:提供随机数

time&datetime模块:时间相关的操作,时间有三种表示方式

logging: 用于记录日志

sys模块:用于提供对解释器相关的操作

os模块:文件和目录操作

hashlib:数据加密,数据校验

json模块:处理JSON字符串,序列化,反序列化

"""
# 序列化:把不可直接存储的数据格式变成可存储数据格式,这个过程就是序列化过程。例如:字典/列表/对象等 => 字符串。
# 反序列化:把可存储数据格式进行格式还原,这个过程就是反序列化过程。例如:字符串还原成字典/列表/对象等。"""
"""序列化 字典数据转换json格式字符串"""
ret = json.dumps(data,indent=None,ensure_ascii=False)
print(ret)#[{"name": "小明", "age": 16}, {"name": "王华", "age": 16}]
"""从指定文件中读取json数据并反序列化"""
data = json.load(open("data.json", "r", encoding="utf-8"))
print(data)  # [{'name': '小明', 'age': 16}, {'name': '王华', 'age': 16}]

4 深浅拷贝:

深浅拷贝的不同是针对二级以上可变数据类型。可变数据类型(字典,集合,列表)才会需要使用深拷贝。深拷贝需要copy.deepcopy()

深拷贝:就是能够把多层元素一块拷贝,后续修改第二层(第三层或者第四层等等)元素的值的时候,不会影响其他深拷贝出来的对象

浅拷贝:只能复制第一层元素,后续修改第二层(第三层或者第四层等等)元素的值的时候,也会影响其他浅拷贝出来的对象

5 变量缓存机制:也叫内存驻留机制。在这个变量缓存机制中,python把一些相同值的变量在内存中指向同一块内存空间,不再重新开辟新的空间。

小数据池:不同的python文件(模块)中的代码里面的相同数据的本应该是不在同一个内存地址当中的, 而是应该全新的开辟一个新空间,但是这样也会占用了更多的内存,所以python定义了小数据池的概念,默认允许小部分数据即使在不同的文件当中,只要数据相同就可以使用同一个内存空间,以达到节省内存的目的。小数据池只针对:int、bool、None关键字 

6 is和==

  • 基于is可以直接判断两个数据的值是否一样,内存地址同一个

  • 基于== 只能判断两个数据的值是否一样

不定长参数的2种写法:

  • 在形参的位置参数左边使用*表示,接收0~多个位置实参,这种情况下,*号左边的形参,在函数内部就是一个元组。在函数定义中使用*args传递非命名键值可变长参数列表

  • 在形参的位置参数左边使用**表示,接收0~多个关键字参数,这种情况下,**号左边的形参,在函数内部就是一个字典。在函数定义中使用**kwargs传递键值可变长参数列表

8 匿名函数:

  • 对于单行函数,使用 lambda 表达式可以省去定义函数的过程,让代码更加简洁;

  • 对于不需要多次复用的函数,使用 lambda 表达式可以在用完之后立即释放,提高程序执行的性能。

# 格式1:
# add = lambda x,y: x + y
# ret = add(10,20)
# print(ret)

# 格式2:
# ret = (lambda x, y: x + y)(10,20) # 声明匿名函数的同时,直接调用了
# print(ret)

9 PEP8规范:

  • 用空格缩进来区分代码层次
  • Python不建议使用分号!除此之外,也不要用分号连接两条语句
  • 冒号、大于小于不等于、感叹号、逗号、括号、引号等等请使用英文状态下的符号
  • 在Python中注释分为两种方式: 单行注释(#号表示):一般用来对一行代码或者几行代码进行注释 多行注释(三对引号表示):一般用与对较多的代码行或代码块进行注释,或者对整个文件进行描述,下图演示了单行注释和多行注释在实际编写代码中的示例。
  • 单引号和双引号都能用来表示一个字符串
  • 顶级定义之间空两行, 方法定义之间空一行。 顶级定义之间空两行, 比如函数或者类定义. 方法定义, 类定义与第一个方法之间, 都应该空一行. 函数或方法中, 某些地方要是你觉得合适, 就空一行。

二 进阶阶段

1 推导式

推导式种类

其中,列表和字典最常用
# 1. 列表推导式,结果是一个列表
[item for item in Iterable]
# 2. 字典推导式,结果是一个字典
{a:b for a,b in iterable.items()}
# 3. 集合推导式,结果是一个集合
{item for item in Iterable}
# 4. 生成器表达式,结果是一个生成器
(item for item in Iterable)

实例

data = [1, -1, 2, -3, 3]
# ret = set()
# for num in data:
#     ret.add(num**2)
# 上面的这种结构代码就可以使用推导式进行简写
ret = {num**2 for num in data}  # 集合推导式{1, 4, 9} 
# ret = [num**2 for num in data] # 列表推导式[1, 1, 4, 9, 9]

2 迭代器与生成器

迭代器:实现了迭代器协议((内置了__iter__和__next__方法)的特殊的可迭代对象),作用是可以快速遍历容器,让原来不可迭代的对象可以使用for循环语句。

生成器:是一种特殊的迭代器,内部实现了迭代器协议,调用了yield关键字的函数(这种函数就是生成器函数,函数的返回值就是生成器对象)。作用是实现协程,生成器可以返回多次结果,每次放回的结果都在一个内存中,所以可以用于遍历或处理大文件,海量数据

3 正则表达式:经常用于数据提取,爬虫数据抓取工作

re模块

三 面向对象

1 面向对象三大特性:

封装:封装就是定义类属性/实例属性只提供给类/对象内部使用。对外提供类方法/实例方法操作类属性/实例方法。对内部属性进行保护,对外提供的操作方法的进行逻辑判断让外界修改类/对象内部的属性,提高数据安全性。

继承:子类可以继承父类的属性或方法,也可以基于父类进行扩展,拥有父类没有的属性或方法,子类可以用自己的方式重写父类方法,提高代码的复用性。

多态:子类对继承的父类的同一个方法,可以有多种不同的实现。但是python中的面向对象的多态是基于鸭子类型来实现的。

反射机制:程序通过字符串的形式操作对象中(查找/获取/删除/添加)的成员,以达到访问、检测和修改对象本身状态或行为的一种能力。在python中一切皆对象(类,实例,模块等都是对象),我们可以通过反射的形式操作对象相关的属性。

getattr(object,name[,default]):获取object对象的name属性的值,如果不存在,则返回默认值default,如果没有设置default,则抛出异常
setattr(object,name,value):设置object对象的name属性的值,如name属性存在则覆盖,name属性不存在则新增name属性
hasattr(object,name):判断object对象的name属性是否存在,返回布尔值
delattr(object,name):删除object对象的name属性

3 抽象类:

定义:只能被子类继承,而不能直接实例化对象的特殊类。

用途:用于定义子类的代码编写规范和编写子类中公有的具体方法。

@abc.abstractmethod:标记一个方法为抽象方法,只定义方法名和参数,而要求子类继承时必须实现具体代码,是个装饰器。
abc.ABC:定义当前类为抽象类,本质上就是一个经过元类实例化的父类
abc.ABCMate:定义当前类为抽象元类,abc.ABC的父类的元类。Python3.4以后建议使用上面的abc.ABC。

4 设计模式

  • 外观模式:隐藏内部类的复杂实现代码的同时,为调用者提供了一个外观接口,以便调用者可以非常轻松的访问程序内部。应用:运维监控系统,在服务器宕机时发出警报通知管理员
  • 策略模式:属于一种对象的行为型模式,指对象有某个行为,但是在不同业务或不同场景中,该行为有不同的实现算法。应用:商品优惠策略
  • 装饰器模式:装饰器模式就是在现有的函数、类外层,套上一段逻辑代码,对其功能进行扩展和延伸,而且不会影响现有函数、类的本身结构。
  • 单例模式:保证一个类,无论调用多少次产生的实例对象,都是指向同一个内存地址。应用:日志记录器,在内存中只会创建一次,在程序中多次使用同一个对象作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象
  • 工厂方法模式:工厂父类负责创建对象的公共接口,工厂子类负责实例化具体对象。
  • 抽象工厂模式:和工厂方法模式基本一致,唯一的区别是,抽象工厂模式可以实现多种对象的实例化,而工厂方法模式只能实现一种对象的实例化。

5 装饰器:

装饰器的2种写法:函数装饰器与类装饰器。而被装饰的3种对象:函数、类、类方法三种。都大同小异。

手写一个装饰器

def decorator(func):
    def wrapper(a, b):
        if type(a) is not int or type(b) is not int:
            print("a或者b不是整数!")
            return 0
        print("a,b是整数!")
        ret = func(a, b)
        return ret
    return wrapper

@decorator  #fn= decorator(fn)
def fn(a, b):
    return a + b
ret = fn(10, 2)
print(f"ret={ret}")
'''
a,b是整数!
ret=12
'''

'''基于装饰器'''
def singleton(cls):
    # 创建一个字典用来保存类的实例对象
    _instance = {}
 
    def _singleton(*args, **kwargs):
        # 先判断这个类有没有对象
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)  # 创建一个对象,并保存到字典当中
        # 将实例对象返回
        return _instance[cls]
 
    return _singleton

基于装饰器实现单例

6 垃圾回收机制:

Python解释器自带一种机制,采用了引用计数法为主标记-清除和分代回收为辅的策略实现了垃圾回收机制。其中,引用计数法用于跟踪和回收垃圾,在引用计数法的基础上,通过标记-清除机制解决容器对象可能产生的循环引用的问题,最后通过分代回收机制以空间换取时间的方式提高垃圾回收的效率。

  • 引用计数:用来记录对象被引用的次数,每当对象被创建或被引用时将该对象的引用次数加一,当对象的引用被销毁时该对象的引用次数减一,当对象的引用次数减到0时,那么所占用的空间也就可以被释放了

  • 标记清除:分为两个阶段:第一个阶段是标记阶段,第二阶段是把没有标记的对象非活动对象进行回收

  • 分代回收:将系统中的全部内存块依据其存活时间划分为不同的集合,每个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减小

7 GIL锁

出现?
单核计算机时代,python实现垃圾回收机制导致的,标记-清除、引用计数、分代回收。

好处?
保证在一个进程下同一时刻,只有一个线程在执行,限制了单核并发能力,保证数据不会因为线程的并发切换导致出现计算偏差。

坏处?
在多核时代,Cpython限制了python在高并发场景对于多线程的并发能力的使用,针对计算密集型的任务有严重影响,但是对于IO密集型的任务并没有任何影响。

8  Lock与GIL的区别:

  1. Lock和GIL,Lock是我们程序中针对单个进程进行添加的。GIL锁是Cpython解释器中默认添加的。Lock针对的进程本身,GIL是针对所有进程下的所有线程

  2. Lock与GIL都是一种互斥锁。GIL是属于CPython解释器管理的,所以不会出现死锁现象。但是Lock是开发人员自己添加的,所以Lock的加锁与解锁都是开发人员自己处理的,因此使用不当则会出现死锁现象。

互斥锁(Lock):对共享数据进行锁定,保证同一时刻只能有一个线程去操作

死锁:两个或两个以上进程或线程执行过程,因争夺资源而造成的一种互相等待的现象若无外力作用,它们都将无法推进下去。

递归锁(RLock):实现同一时间允许多个进程上多把锁只允许同一时间只有一个进程或线程修改数据。一般用来解决多把锁产生的死锁问题

四 网络编程

1 TCP和UDP

三次握手:
    首先,客户端会发送一段报文(SYN=1, Seq=x)到服务端,
    然后,服务端接收到报文进行解析,接着返回一段报文(SYN=1,ACK=1,  ack=x+1,seq=y),
    接着,客户端接收到服务端响应的报文,再给服务端发送一次报文(ACK=1,ack=y+1,seq=x+1)

四次挥手:
    首先,客户端会发送一段报文(FIN=1,seq=x)到服务端,
    然后,服务端接收到报文进行解析,接着返回一段报文(ACK=1,Seq=z,ack=x+1),
    接着,服务端会响应一段报文(FIN=1,ACK=1,seq=y,ack=x+1),
    最后,客户端接收到报文,再次发送一段报文(ACK=1,seq=x+1,ack=y+1)给服务端

三次握手的原因:三次握手,避免重复连接,同时也避免了握手过程客户端单方断开的情况。

2 socket位于OSI七层模型的第几层

Socket是存在于应用层与传输层之间的接口,是方便开发者用于实现复杂的TCP/UDP协议所封装的一套函数

3 粘包问题:A端多次发送的数据,到达B端被接收时会存在一次性接受A端多次发送数据的情况。

解决:发送端给每个数据包添加包首部,首部中应该至少包含数据包的长度,这样接收端在接收到数据后,通过读取包首部的长度字段,便知道每一个数据包的实际长度了。

多任务的实现有以下3种方式:

  • 进程:是操作系统资源分配和独立运行的最小单位。实现多进程模块:mutiprocessing

  • 线程:是进程内的一个任务执行独立单元,是任务调度和系统执行的最小单位。实现多线程模块:Threading

  • 协程:是用户态的轻量级线程,协程的调度完全由用户控制,主要为了一个线程内多个任务交替执行。实现多协程模块:asynio

5 同步异步,阻塞非阻塞

6 并发,并行,串行

7 进程间的通信:管道,消息队列,共享内存

效率最高的是共享内存因为进程可以直接读写内存,而不需要任何数据的拷贝,对于像管道和消息队里等通信方式,则需要再内核和用户空间进行四次的数据拷贝。

五 数据库

1 查询数据操作

2 InnoDB存储引擎,是MySQL当前版本(5.5以后)的默认存储引擎,具有支持事务处理(transaction),外键约束(foreign key),行锁设计,崩溃恢复历史回滚等。MyISAM存储引擎,是MySQL早期版本(5.5以前)的默认存储引擎,拥有较高的插入、查询速度,表锁设计,支持全文索引的特点,但不支持事务处理和外键约束,也不支持崩溃恢复。

InnoDB与MyISAM的区别:

锁设计,InnoDB支持表级锁((table-level locking))与行级锁(row-level locking),而myISAM只支持表级锁。用户在操作myISAM类型表时,select,update,delete,insert等语句都会给表自动加锁,导致其他客户端连接的数据操作都会被阻塞,因此并发访问受限。当然,InnoDB虽然提供了行级锁,但也只是在使用了索引时是有效的,如果没使用索引也会锁全表,行锁大幅度提高了多用户并发操作的性能。

事务安全,InnoDB支持完整的事务安全机制(ACID),具有提交(commit)和回滚(rollback)事务的能力,所以在写入数据时可以有效保证数据的安全性以及一致性。

外键约束,MyISAM不支持,而 InnoDB 支持。但是开发中一般不在数据库使用外键,而是在应用层实现逻辑外键或虚拟外键,使用外键会造成级联更新,且级联更新是强阻塞,存在数据库更新风暴的风险;外键使用时也会影响数据库的插入速度。因为插入一张表的时候,mysql会自动去检查关联的外键所在表的全部数据是否一致。

主键约束,MyISAM允许没有主键的表存在。InnoDB表必须有主键,如果没有设定主键,就会自动生成一个用户不可见的6字节隐藏列作为主键列(对于用户而言,MyISAM与InnoDB都可以创建没有外键的表)。

崩溃恢复,MyISAM不支持,而InnoDB支持。使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log(重做日志)、undo log(回滚日志)、bin log(二进制日志)。

3 存储过程:一个存储过程是一个可编程的函数,它在数据库中创建并保存,一般由 SQL 语句和一些特殊的控制结构组成。目的是以后需要数据库提供已定义好的存储过程的功能相同的服务时,只需调用“CALL 存储过程名字”即可自动完成。这样即可以大大提高数据库的处理速度,同时也可以提高数据库编程的灵活性。适用于一个完整操作需要多条 SQL 语句处理多个表完成。

4 触发器:在预设条件满足以后,自动执行的SQL语句的数据库特性。触发器是与表有关的数据库对象,指在 insert/update/delete 之前或之后,触发并执行触发器中预定义的SQL语句集合。触发器的这种特性可以协助应用程序在数据库端确保数据的完整性 ,常用于日志记录, 数据校验等操作。

5 事务:是以功能业务作为逻辑单位,把一条或多条SQL语句组成一个不可分割的操作序列来执行的数据库机制。事务适用于多用户同时操作的数据库系统的场景,如银行、保险公司及证券交易系统等等要求数据一致性或完整性比较高的场景。

"""基本使用"""
begin;
update users set money=money-200 where name='小明';
SAVEPOINT s1; -- POINT就是事务的节点,savepoint可以给当前位置打个标记,将来如果不希望完全回滚事务,则可以选择回滚到某一个事务节点。p1是自定义的事务节点名称
update users set money=money+100 where name='小红';
SAVEPOINT p2;
update users set money=money+100 where name='小白';
SAVEPOINT p3;

ROLLBACK TO s1;
select * from users; -- 注意,这里仅仅是事务内部的回滚,并没有退出事务操作的,此时还在事务内部。
rollback; -- 或执行commit; 此时才是真正的退出事务。

6 事务的四大特性:

  1. 原子性(Atomicity):事务内的所有DML语句,作为一个不可分割的整体,要么都成功,要么都失败,由redo log(重做日志)来实现

  2. 一致性(Consistency):事务执行前后数据完整性一致的,由undo log(回滚日志)来实现。

  3. 隔离性(Isolation):事务执行过程中对其他事务可以设置不同的隔离级别,隔离性由锁来实现不同的隔离级别(四种隔离级别)

  4. 持久性(Durability):事务一旦提交,其结果就是永久性更改的,由redo log(重做日志)来实现

7 四种隔离级别(mysql 的默认隔离级别可重复读)以下隔离级别由低到高

RU读取未提交内容:一个事务可以读取另一个未提交事务的数据。导致也是脏读

RC读取提交内容:一个事务要等另一个事务提交后才能读取数据。解决脏读,但会导致一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读

RR可重复读:就是在开始读取数据(事务开启)时,不再允许修改操作。可能还会有幻读问题(同样的条件 , 第 1 次和第 2 次读出来的记录数不一样)。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

serializable(可串行化):是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

9 索引:可以帮助MySQL高效获取数据数据结构是一种以空间换时间策略用硬盘空间保存索引数据位置的映射关系在查询数据时,如果有字段被设置了索引,则MySQL查询优化器会根据索引查找到最优的数据查询计划,可以缩短数据查询所需要消耗的时间但是数据表在执行创建、删除、修改操作时,因为数据库需要时刻维护索引与数据位置的关系,所以会耗费额外的资源来完成表的索引检索操作,建议在读多写少的时候创建合适数量的索引。

索引一般用在排序(order by),查询条件(where),字段投影(select)后边

10 索引类型:

  1. 普通索引:是最基本的索引,它没有任何限制。CREATE INDEX index_name ON table(column(length))
  2. 唯一索引:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
    CREATE TABLE `table` (
    `id` int(11) NOT NULL AUTO_INCREMENT ,
    ..
    UNIQUE indexName (title(length))
    );

  3. 主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引。
  4. 组合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合。 
    ALTER TABLE `table` ADD INDEX name_city_age (name,city,age);

11 建立索引适用情况:

1. 主键自动建立唯一索引
2. 频繁作为查询条件的字段应该创建索引
3. 查询中与其它表关联的字段,外键关系建立索引
4. 单列/组合索引的选择问题(在高并发下倾向创建组合索引)
5. 查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
6. 查询中统计或者分组字段

12 不适合索引情况:

1. Where条件里用不到的字段不创建索引
2. 表记录太少(300w以上建)
3. 写多读少的表(提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件)
4. 数据重复且分布平均的表字段,因此应该只为最经常查询和最经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。(比如:国籍、性别)

13 python连接并操作mysql,通常是以下2种方式:

  1. 数据库驱动模块:pymysql(用于 Python3) 、mysqldb(MySQLdb 用于 Python2 的环境模块, Python3中不支持)。

  2. 数据库ORM模块:SQLAlchemy。

不管哪一种方式,mysql都只能识别SQL语句,所以上面的几个模块的作用是充当客户端发送sql语句通过socket通信间接并操作mysql。当然,其中第二种操作方式,是基于第一种方式而进行高度封装实现的。

14 数据库优化方案:

  • 优化索引SQL语句分析慢查询

  • 设计表的时候严格根据数据库的设计范式来设计数据库

  • 使用缓存,把经常访问到的数据,而且不需要经常变化的数据放在缓存中,能节约磁盘IO

  • 优化硬件:采用SSD,使用磁盘队列技术(raid0,1,5)

  • 垂直分表:把一些不经常读的数据放在一张表里,节约磁盘IO

  • 主从分离读写:采用主从复制吧数据库的读操作和写操作分离

  • 分库分表分机器(数据量特别大)

  • 选择合适的表引擎,参数上优化

16 

乐观锁:指的是在操作数据的时候非常乐观,乐观地认为别人不会同时修改数据,因此乐观锁默认是不会上锁的,只有在执行更新的时候才会去判断在此期间别人是否修改了数据,如果别人修改了数据则放弃操作,否则执行操作。

悲观锁:指的是在操作数据的时候比较悲观,悲观地认为别人一定会同时修改数据,因此悲观锁在操作数据时是直接把数据上锁,直到操作完成之后才会释放锁,在上锁期间其他人不能操作数据。

17 关系型非关系数据库区别

1.关系型数据库:
优点:
1、易于维护:都是使用表结构,格式一致;
2、使用方便:SQL语言通用,可用于复杂查询;
3、复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
缺点:
1、读写性能比较差,尤其是海量数据的高效率读写;
2、固定的表结构,灵活度稍欠;
3、高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。

2.非关系型数据库
优点:
1、格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛.
2、速度快:可以使用硬盘或者内存作为载体,而关系型数据库只能使用硬盘;
3、成本低:数据库部署简单,基本都是开源软件。

缺点:
1、不提供sql支持,学习和使用成本较高;
2、无事务处理;

 

六 ORM框架

1 ORM(对象关系映射器):是一种基于面向对象操作提供的数据库的框架。在各种语言中都有对应的ORM实现,是对底层数据库原生SQL语句操作的高度且抽象的封装。python常用的ORM有:django提供的ORM,SQLAlchemy。相关操作

O是Object,也就类对象的意思。

R是Relational,译作联系或关系,也就是关系型数据库中数据表的意思。

M是Mapper,是映射的意思,表示类对象和数据表的映射关系。

优点:
1. 数据模型类都在一个地方定义,更容易更新和维护,也利于重用代码。
2. ORM有现成的工具,很多功能可以自动完成,例如数据消除,预处理,还有事务等操作的封装。
3. 基于ORM的业务代码量少,更简单直观。
4. 天然适合适用于MVC/MVT架构中,更利于第三框架的代码整合
5. 基于 ORM 的业务代码比较简单,代码量少,语义性好,容易理解。 6. 新手只需要通过操作模型对象即可同步修改数据表中的数据,而不需要编写底层原生SQL语句 7. ORM高度抽象了底层数据库连接,对于使用者而言,不必关注数据库之间带来的差异,将来切换数据库,只需要更换底层的数据库连接驱动即可。 缺点: 1. ORM库不是轻量级工具,有一定的学习成本,需要花费时间与精力来学习掌握它的使用。 2. 对于复杂的业务查询(例如远程的关联查询),ORM表达会比原生的SQL语句要更加困难,也更加复杂。 3. ORM抽象掉了数据库底层,开发者无法理解底层的数据库操作,提供了维护成本。 4. ORM最终还是基于底层数据库驱动基于SQL语句来操作数据库,所以要比直接使用原生SQL语句的性能要差。 感受: 开发中因为对于ORM的使用是需要有一定的技术要求的,而且ORM使用操作相对高度统一的,所以在团队开发项目过程中,可以很方便的调用他人编写的模型代码,工作交接时交接成本相对低廉。 把数据表与类对象进行一对一的映射,让我们可以通过类对象来操作对应的数据表,减少了将来切换数据库带来的迁移成本。
 

七 Django

1 设计模式

MVC:Model:数据库操作代码  crotl:视图代码逻辑,view:模版

MVT:model:数据库操作代码 /view:代码逻辑/Template:展示界面效果。视图调用

MVM:M:data数据。 V:template M:虚拟DOM对象,全局对象 (前端)

2 Django的中间件:是 Django 请求/响应处理的钩子框架用于全局改变 Django 的输入或输出。

内置中间件

Csrfmiddleware:给开发者用于防止网站用户遭到csrf的攻击(跨站请求伪造:利用用户在不知情的情况下实现伪造表单提交给服务端中进行攻击的手段)

GzipMiddleware:Gzip压缩所有浏览器的响应,节省带宽和传输时间

跨域的中间件:corsheaders

自定义中间件:函数中间件,类中间件

Django的请求生命周期:

  • 1 用户在浏览器中输入url,发送一个GET方法的request请求

  • 2 Django中封装了WSGI服务器,监听端口接受这个request请求,在进行解析封装,传送到中间件中,对请求进行校验或处理

  • 3 再传输到路由系统中进行路由分发,匹配相对应的视图函数进行业务逻辑处理。

  • 4 调用modles模型层中表对象,通过orm拿到数据库(DB)的数据

  • 5 同时拿到templates中相应的模板进行渲染,然后将这个封装了模板response响应传输到中间件中,依次进行处理,最后通过WSGI再进行封装处理,响应给浏览器展示给用户。

八 DRF

 

 

原文地址:http://www.cnblogs.com/daminghuahua/p/16863125.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性