a. Python(解释型语言、弱类型语言)和其余语言的区别?
1、编译型语言:一次性,将所有的程序编译成二进制文件,而后在运行。(c,c++ ,go)
运行速度快。开发效率低
2、解释型语言:当你的程序运行时,一行一行的解释,并运行。(python , PHP)
运行速度相对较慢,可是调试代码很方便,开发效率高
html
3、混合型:(C#,Java)前端
python特色:java
CPython 当咱们从Python官方网站下载并安装好Python 3.6后,咱们就直接得到了一个官方版本的解释器:CPython。这个解释器是用C语言开发的,因此叫CPython。在命令行下运行python就是启动CPython解释器。 CPython是使用最广的Python解释器。教程的全部代码也都在CPython下执行。 IPython IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互方式上有所加强,可是执行Python代码的功能和CPython是彻底同样的。比如不少国产浏览器虽然外观不一样,但内核其实都是调用了IE。 CPython用>>>做为提示符,而IPython用In [序号]:做为提示符。 PyPy PyPy是另外一个Python解释器,它的目标是执行速度。PyPy采用JIT技术,对Python代码进行动态编译(注意不是解释),因此能够显著提升Python代码的执行速度。 绝大部分Python代码均可以在PyPy下运行,可是PyPy和CPython有一些是不一样的,这就致使相同的Python代码在两种解释器下执行可能会有不一样的结果。若是你的代码要放到PyPy下执行,就须要了解PyPy和CPython的不一样点。 Jython Jython是运行在Java平台上的Python解释器,能够直接把Python代码编译成Java字节码执行。 IronPython IronPython和Jython相似,只不过IronPython是运行在微软.Net平台上的Python解释器,能够直接把Python代码编译成.Net的字节码。 小结: Python的解释器不少,但使用最普遍的仍是CPython。若是要和Java或.Net平台交互,最好的办法不是用Jython或IronPython,而是经过网络调用来交互,确保各程序之间的独立性。
一、缩进使用4个空格键。不建议使用tab
二、运算符左右隔空一格
三、类名首字母大写
四、函数命名所有使用小写,能够用下划线分割
五、常量或全局变量使用大写,能够用下划线分割
六、不建议import os,time
七、建议使用块注释
参考python
print("转换为二进制为:", bin(dec)) int("01010101",2) print("转换为八进制为:", oct(dec)) print("转换为十六进制为:", hex(dec))
def addr2dec(addr): "将点分十进制IP地址转换成十进制整数" items = [int(x) for x in addr.split(".")] print(items) return sum(items[i] << [24, 16, 8, 0][i] for i in range(4)) print(addr2dec("10.3.9.12"))
python2内容进行编码(默认ascii),而python3对内容进行编码的默认为utf-8。
ascii 最多只能用8位来表示(一个字节),即:2**8 = 256,因此,ASCII码最多只能表示 256 个符号。 1-->48 A-->65 a-->97
unicode 规定虽有的字符和符号最少由 16 位来表示(2个字节),即:2 **16 = 65536,
UTF-8 是对Unicode编码的压缩和优化,他再也不使用最少使用2个字节,而是将全部的字符和符号进行分类:
A 1个字节 欧洲 一个字 2个字节 亚洲 一个子 3个字节
gbk A : 1个字节 中 :两个字节
v1 = 1 or 3
#1
v2 = 1 and 3
#3
v3 = 0 and 2 and 1 #0
v4 = 0 and 2 or 1 #1
v5 = 0 and 2 or 1 or 4 #1
v6 = 0 or False and 1 #Falsemysql
机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据。react
字节码是一种中间状态(中间码)的二进制代码(文件)。须要直译器转译后才能成为机器码。linux
一、默认解释器编码:
py2: ascii
py3: utf-8
二、字符串:
py2: str:字符串 -->字节
unicode:u"shh"
py3: bytes 和 str
三、range和xrange
py2 range返回list xrange返回生成器
py3 range返回生成器
四、py2 int、long
py3 int
五、py2 yield
py3 yiled、 yield from
六、py2 新式类和经典类
py3 新式类
七、py2 raw_input py3 input
八、py2 print py3 print()
python3去除了long类型,如今只有一种整型——int,但它的行为就像python2版本的longnginx
0 空列表字符串 负数 不成立的表达式 None 等c++
readlines 返回一个列表程序员
xreadlines 返回一个生成器
不可哈希:list dict set 可哈希:int str bool None tuple
- 字符串 strip()去除
find()找不到返回-1 、index()找不到报错
split()分割
join()拼接
replace()替换
- 字典 pop() 删除 建立字典的三种方法:一、直接表达 二、dict(name="cao") 三、dict.formkeys(["key","key"],value)
update()
clear()清空
get()
dict.items() - 元组tuple 只读 按str索引方法去查 - 列表 append()
inset()按索引增长
extend()迭代增长
conut()
sort()排序
index()
rserver()反转 - 集合 add() update() remove() del() pop() clear() 交集$ 并集| 差集-
collections Python内建的一个集合模块,提供了许多有用的集合类。
Counter是一个简单的计数器,例如,统计字符出现的个数:
OrderedDict能够实现一个FIFO(先进先出)的dict,当容量超出限制时,先删除最先添加的Key:
deque是为了高效实现插入和删除操做的双向列表,适合用于队列和栈:
defaultdict使用dict时,若是引用的Key不存在,就会抛出KeyError。若是但愿key不存在时,返回一个默认值,就能够用defaultdict:
*args :接收全部按照位置传的参数,接收到的是参数组成的元祖
**kwargs :接收全部按照关键字传的参数,接收到的是参数组成的字典
引用计数 (对象被引用时+1,引用的对象被删除时-1)
标记清除
分代回收(系统中的全部内存块根据其存活时间划分为不一样的集合,每个集合就成为一个“代”,垃圾收集的频率随着“代”的存活时间的增大而减少)
在Python中对象的赋值其实就是对象的引用。当建立一个对象,把它赋值给另外一个变量的时候,python并无拷贝这个对象,只是拷贝了这个对象的引用而已。
浅拷贝:拷贝了最外围的对象自己,内部的元素都只是拷贝了一个引用而已。也就是,把对象复制一遍,可是该对象中引用的其余对象我不复制
深拷贝:外围和内部元素都进行了拷贝对象自己,而不是引用。也就是,把对象复制一遍,而且该对象中引用的其余对象我也复制。
###############################
浅拷贝copy ,第一层建立的是新的内存地址,而从第二层开始,指向的都是同一个内存地址,因此,对于第二层以及更深的层数来讲,与原内存地址不变。
l1 = [1,[22,33,44],3,4,] l2 = l1.copy() l1[1].append('55') print(l1,id(l1),id(l1[1])) #[1, [22, 33, 44, '55'], 3, 4] 1787518244744 1787518244808 print(l2,id(l2),id(l2[1])) #[1, [22, 33, 44, '55'], 3, 4] 1787518244616 1787518244808 ############ l1[1].append("cao") print(l1) #[1, [22, 33, 44, '55', 'cao'], 3, 4] print(l2) #[1, [22, 33, 44, '55', 'cao'], 3, 4] ######################### l1[0] = "chao" print(l1) #['chao', [22, 33, 44, '55'], 3, 4] print(l2) #[1, [22, 33, 44, '55'], 3, 4]
深拷贝deepcopy,两个是彻底独立的,改变任意一个的任何元素(不管多少层),另外一个绝对不改变。
import copy l1 = [1,[22,33,44],3,4,] l2 = copy.deepcopy(l1) print(id(l1[1])) print(id(l2[1])) print("="*20) l1[0] = 111 print(l1) print(l2) print("="*20) l1[1].append('barry') print(l1) print(l2) ############ 1742824920904 1742824920520 ==================== [111, [22, 33, 44], 3, 4] [1, [22, 33, 44], 3, 4] ==================== [111, [22, 33, 44, 'barry'], 3, 4] [1, [22, 33, 44], 3, 4]
print('\n'.join([' '.join(['%s*%s=%-2s' % (j, i, i * j) for j in range(1, i + 1)]) for i in range(1, 10)]))
v = dict.fromkeys(['k1','k2'],[]) print(v) v["k1"].append(666) print(v) v["k1"] = 777 print(v)
{'k1': [], 'k2': []}
{'k1': [666], 'k2': [666]}
{'k1': 777, 'k2': [666]}
##############
def num():
return [lambda x:x+1 for i in range(4)]
print([m(2) for m in num()]) #[3,3,3,3]
print([m(1) for m in num()]) #[2,2,2,2]
################
print([ i % 2 for i in range(10) ]) #[0,1,0,1,0,1,0,1,0,1]
print(( i % 2 for i in range(10) )) #生成器
###################
a. 1 or 2 1
b. 1 and 2 2
c. 1 < (2==2) False
d. 1 < 2 == 2 Ture
not > and > or
- 函数参数传递的是什么? 引用、内存地址
#魔性的用法:默认参数尽可能避免使用可变数据类型 类型一: lst = [] def func(l = lst): #默认参数 l.append(1) print(l) func() #[1] func() #[1,1] 默认参数只会被执行一次:第一次调用函数时,默认参数被初始化为【】,之后每次调用时都会使用已经初始化的【】。 类型二: lst = [] def func(l = lst): l.append(1) print(l) func([]) #[1] func([]) #[1] 类型三: def func(a1,a2=[]): a2.append(a1) print(a2) func(1) #[1,] func(3,[]) #[3,] func(4) #[1,4] 类型四: def func(a1,a2=[]): a2.append(a1) return a2 l1 = func(1) print(l1) # [1,] l2 = func(3,[]) print(l2) # [3, ] l3 = func(4) print(l3) # [1,4] 类型五: def func(a1,a2=[]): a2.append(a1) return a2 l1 = func(1) # l1=[1,4] l2 = func(3,[]) # l2=[3,] l3 = func(4) # l3=[1,4] print(l2) print(l1) print(l3)
简单的函数: my_lambda = lambda arg : arg + 1
简单的条件语句: val= "cao" if 1==1 else "chao"
列表生成式 s1=[i*2 for i in range(5)] print(s1) 生成器表达式 s=(i*2 for i in range(5) ) print(s.__next__()) print(next(s))
val = [lambda :i + 1 for i in range(10)] [function,funtion...] print(val,type(val)) #<class 'list'> print(val[0],type(val[0])) #<class 'function'> data = val[0]() print(data) #10
应用到闭包函数:
当调用函数的时候,都会优先在外部做用域中查找i变量,这时列表生产式中循环立马执行,最后i赋值为9
def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >>>bar = foo() >>>bar() 12
简单的说,这种内部函数可使用外部函数变量的行为,就叫闭包。
闭包的意义与应用:延迟计算:
闭包的意义:返回的函数对象,不只仅是一个函数对象,在该函数外还包裹了一层做用域,这使得,该函数不管在何处调用,优先使用本身外层包裹的做用域
#应用领域:延迟计算(原来咱们是传参,如今咱们是包起来)
装饰器就是闭包函数的一种应用场景
- map - filter
map()函数接收两个参数,一个是函数,一个是可迭代对象,map将传入的函数依次做用到序列的每一个元素,并把结果做为新的list返回。 def mul(x): return x*x n=[1,2,3,4,5] res=list(map(mul,n)) print(res) #[1, 4, 9, 16, 25] filter()函数接收一个函数 f 和一个list,这个函数 f 的做用是对每一个元素进行判断,返回 True或 False, filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。 def is_odd(x): return x % 2 == 1 v=list(filter(is_odd, [1, 4, 6, 7, 9, 12, 17])) print(v) #[1, 7, 9, 17]
- isinstance - type
isinstance() 函数来判断一个对象是不是一个已知的类型,相似 type()。
isinstance() 与 type() 区别:
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
若是要判断两个类型是否相同推荐使用 isinstance()。
- zip
zip() 函数用于将可迭代的对象做为参数,将对象中对应的元素打包成一个个元组,而后返回由这些元组组成的列表。 >>>a = [1,2,3] >>> b = [4,5,6] >>> c = [4,5,6,7,8] >>> zipped = zip(a,b) # 打包为元组的列表 [(1, 4), (2, 5), (3, 6)] >>> zip(a,c) # 元素个数与最短的列表一致 [(1, 4), (2, 5), (3, 6)] >>> zip(*zipped) # 与 zip 相反,可理解为解压,返回二维矩阵式 [(1, 2, 3), (4, 5, 6)]
- reduce
from functools import reduce
reduce() 函数会对参数序列中元素进行累积。 用传给reduce中的函数 function(有两个参数)先对集合中的第一、2个元素进行操做,获得的结果再与第三个数据用function函数运算,最后获得一个结果。 >>>def add(x, y) : # 两数相加 ... return x + y ... >>> reduce(add, [1,2,3,4,5]) # 计算列表和:1+2+3+4+5 15 >>> reduce(lambda x, y: x+y, [1,2,3,4,5]) # 使用 lambda 匿名函数 15
生成器:一个函数调用时返回一个迭代器,或 函数中包含yield语法,那这个函数就会变成生成器;
应用场景:
- range/xrange - py2: range(1000),当即建立;xrange(1000)生成器; - py3: range(1000)生成器; 没有xrange
-redis获取值
hscan_iter 利用yield封装hscan建立生成器,实现分批去redis中获取数据
迭代器:含有__iter__和__next__方法 (包含__next__方法的可迭代对象就是迭代器)
特色:
访问者不须要关心迭代器内部的结构,仅需经过next()方法不断去取下一个内容(惰性计算)
不能随机访问集合中的某个值 ,只能从头至尾依次访问
访问到一半时不能往回退
便于循环比较大的数据集合,节省内存
可迭代对象:一个类内部实现__iter__方法且返回一个迭代器。
应用场景:
- wtforms中对form对象进行循环时候,显示form中包含的全部字段。
- 列表、字典、元组
总结:若是想要让一个对象能够被for循环,那么就须要在当前类中定义__iter__
问题:什么是装饰器?
在对原函数不进行修改时,在函数执行前和执行后添加功能
问题:手写装饰器
import functools
def warpper(func):
@functools.wraps(func) #保留原函数信息
def inner(*args,**kwargs):
#执行函数前
return func(*args,**kwargs)
#执行函数后
return inner
# 1. 执行wapper函数,并将被装饰的函数当作参数。 wapper(index)
# 2. 将第一步的返回值,从新赋值给 新index = wapper(老index)
@warpper #index=warpper(index)
def index(x):
return x+100
问题:应用场景
django: csrf 内置认证、缓存
flask: 路由、before_request
带参数装饰器:flask:路由
CBV as_view()
偏函数: import functools def func(a1, a2, a3): return a1 + a2 + a3 new_func = functools.partial(func, 11, 2) #将11,2依次传入到func函数的前两个参数 print(new_func(3))
应用场景
falsk中取值时 经过localproxy 、偏函数、localstack、local
-继承、封装、多态(简单描述)
python中一切皆对象
封装:
其实就是将不少数据封装到一个对象中,相似于把不少东西放到一个箱子中,
如:一个函数若是好多参数,起始就能够把参数封装到一个对象再传递。
应用场景:
- django rest framework中的request对象。
- flask中:request_context/app_context对象
继承:
若是多个类中都有共同的方法,那么为了不反复编写,就能够将方法提取到基类中实现,让全部派生类去继承便可。
应用场景:
- rest frmawork 视图
- 版本、认证、分页
多态:
python自己就是多态的,崇尚鸭子模型,只要会呱呱叫我么就认为它是鸭子。
class A: def send(self): print("A") class B: def f(self): print("B") def func(arg): arg.send() obj = A() func(obj)
-双下划线:
__getattr__
-CBV -django配置文件 -wtforms中的Form()示例化中 将"_fields中的数据封装到From类中"
__mro__ wtform中 FormMeta中继承类的优先级 __dict__ __new__ ,实例化可是没有给当前对象 wtforms,字段实例化时返回:不是StringField,而是UnboundField rest frawork many=Turn 中的序列化
单例模式 __call__ flask 请求的入口app.run() 字段生成标签时:字段.__str__ => 字段.__call__ => 插件.__call__ __iter__ 循环对象是,自定义__iter__ wtforms中BaseForm中循环显示全部字段时定义了__iter__ -metaclass - 做用:用于指定当前类使用哪一个类来建立 - 场景:在类建立以前定制操做 示例:wtforms中,对字段进行排序。
子类继承父类的方法,其继承顺序按照__mro__
staticmethod
classmethod 须要传入参数cls当前类
两种方法都不须要实例化就可使用l类.方法或对象.方法
Python的类能够继承多个类,Python的类若是继承了多个类,那么其寻找方法的方式有两种
当类是经典类时,多继承状况下,会按照深度优先方式查找
当类是新式类时,多继承状况下,会按照广度优先方式查找
简单点说就是:经典类是纵向查找,新式类是横向查找
经典类和新式类的区别就是,在声明类的时候,新式类须要加上object关键字。在python3中默认全是新式类
from types import MethodType,FunctionType class Foo(object): def fetch(self): pass Foo.fetch 此时fetch为函数 print(isinstance(Foo.fetch,MethodType)) print(isinstance(Foo.fetch,FunctionType)) # True obj = Foo() obj.fetch 此时fetch为方法 print(isinstance(obj.fetch,MethodType)) # True print(isinstance(obj.fetch,FunctionType))
单例模式:一个类只能有一个实例化对象
应用场景:Django中的admin组件中admin.site()就是由单例模式建立的,其中封装了全部的表对象
#基于new
class Singleton(object):
每一次实例化的时候,返回同一个instance对象 def __new__(cls,*args,**kwargs): if not hasattr(cls,"instance"): cls.instace=super(Singleton,cls).__new__(cls,*args,**kwargs) return cls.instace a=Singleton() b=Singleton() print(a,b) print(a is b)
#基于装饰器
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=None):
self.x=x
c=A(2)
b=A(3)
print(c is b)
os、sys、json、re、logging、random、time、requests、beautifulsoup,
os模块是与操做系统交互的一个接口 ,提供了不少方法来处理文件和目录
os.remove(‘path/filename’) 删除文件 os.rename(oldname, newname) 重命名文件 os.walk() 生成目录树下的全部文件名 os.chdir('dirname') 改变目录 os.getcwd() 取得当前工做目录 os.path.getsize() 返回文件大小
sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境。
sys.argv 命令行参数List,第一个元素是程序自己路径 sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1) sys.version 获取Python解释程序的版本信息 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操做系统平台名称
logging :记录日志,分为五种级别,debug,info ,warning,error,critical
random
random.random() 0-1随机数
random.randint(1,9) 1-9 随机整数
requests 获取页面html和xml
json 序列化
. 匹配除换行符之外的任意字符 \w 匹配字母或数字或下划线 \s 匹配任意的空白符 \d 匹配数字 \n 匹配一个换行符 \t 匹配一个制表符 \b 匹配一个单词的结尾 ^ 匹配字符串的开始 $ 匹配字符串的结尾 \W 匹配非字母或数字或下划线 \D 匹配非数字 \S 匹配非空白符 a|b 匹配字符a或字符b () 匹配括号内的表达式,也表示一个组 [...] 匹配字符组中的字符 [^...] 匹配除了字符组中字符的全部字符 用法说明 * 重复零次或更屡次 + 重复一次或更屡次 ? 重复零次或一次 {n} 重复n次 {n,} 重复n次或更屡次 {n,m} 重复n到m次
一、写一个邮箱、手机号、IP
#匹配手机号 import re def phone(arg): s=re.match("^(13|14|15|18)[0-9]{9}$",arg) if s: return "正确" return "错误" print(phone("23722751552"))
#匹配邮箱
re.match("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$",arg)
#匹配IP
re.match("\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b",arg)
?: 优先匹配
\b 匹配一个单词的结尾
re.match只匹配字符串的开始,若是字符串开始不符合正则表达式,则匹配失败,函数返回None;
re.search匹配整个字符串,直到找到一个匹配。
1 import re 2 s="fnfffidvvgf" 3 4 m=re.match("fi",s) 5 print(m) #None 6 s=re.search("fi",s).group() 7 print(s) #fi
贪婪匹配: 匹配1次或屡次<.+> 匹配0次或屡次<.*>
非贪婪匹配:匹配0次或1次<.?>
[i**2 for i in range(1,11)]
list(set([1,2,45,5,2]))
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] def search(someone, li): l = -1 h = len(li) while l + 1 != h: m = int((l + h) / 2) if li[m] < someone: l = m else: h = m p = h if p >= len(li) or li[p] != someone: print("元素不存在") else: str = "元素索引为%d" % p print(str) search(1, li) # 元素索引为2
方法一: 使用os.walk file-- 是你所要便利的目录的地址, 返回的是一个三元组(root,dirs,files)。 root 所指的是当前正在遍历的这个文件夹的自己的地址 dirs 是一个 list ,内容是该文件夹中全部的目录的名字(不包括子目录) files 一样是 list , 内容是该文件夹中全部的文件(不包括子目录) def open_2(file): for root, dirs , files in os.walk(file): print("ss",files) for filename in files: print(os.path.abspath(os.path.join(root, filename))) #返回绝对路径 open_2("F:\搜索") 方法二: import os def open(files): for dir_file in os.listdir(files): # print("ss",dir_file) #递归获取全部文件夹和文件 files_dir_file = os.path.join(files, dir_file) if os.path.isdir(files_dir_file): #是否是文件夹 open(files_dir_file) else: print(files_dir_file) open("F:\搜索") 并将下面的全部文件内容写入到一个文件中 def open_2(file): for root, dirs , files in os.walk(file): for filename in files: with open(os.path.abspath(os.path.join(root, filename)), "r") as f: for i in f.readlines(): print(i) with open("./cao.txt","a",encoding="utf-8") as f2: f2.write(i) f2.write("\n") open_2("F:\搜索")
1 # 建立一个文件 2 open("chao.txt","w",encoding="utf-8") 3 import os
#删除文件 4 os.remove("chao.txt")
一、pip3 包管理器
二、源码安装
-下载、解压
-python setup.py bulid
-python setup.py install
使用python内置的排列组合函数(不放回抽样排列) product 笛卡尔积 (有放回抽样排列) permutations 排列 (不放回抽样排列) combinations 组合,没有重复 (不放回抽样组合) combinations_with_replacement 组合,有重复 (有放回抽样组合) import itertools print(len(list(itertools.permutations('12345', 3)))) # 60
反射的核心本质就是以字符串的形式去导入个模块,经过字符串的形式操做对象相关的属性
Django中的 CBV就是基于反射实现的。
导入模块:
x=__import__("time")
print(x.time())
指定当前类是由那个类建立的
默认为type
- 场景:在类建立以前定制操做 - 示例:wtforms中,对字段进行排序。
try: fh = open("testfile", "w") try: fh.write("这是一个测试文件,用于测试异常!!") finally: print "关闭文件" fh.close() except IOError: print "Error: 没有找到文件或读取文件失败" raise抛异常 inputValue=input("please input a int data :") if type(inputValue)!=type(1): raise ValueError else: print inputValue
整数、字符创、字典、列表、bool、None
重写default() import json import datetime dic = { 'k1':123, 'ctime':datetime.datetime.now() } class MyJSONEncoder(json.JSONEncoder): def default(self,o): if isinstance(o,datetime.datetime): return o.strftime("%Y-%m-%d") else: return super(MyJSONEncoder,self).default(o) v=json.dumps(dic,cls=MyJSONEncoder) print(v)
json.dumps(xxxx,ensure_ascii=False)
上下文管理器:
在使用Python编程中,能够会常常碰到这种状况:有一个特殊的语句块,在执行这个语句块以前须要先执行一些准备动做;当语句块执行完成后,须要继续执行一些收尾动做。 例如:当须要操做文件或数据库的时候,首先须要获取文件句柄或者数据库链接对象,当执行完相应的操做后,须要执行释放文件句柄或者关闭数据库链接的动做。 又如,当多线程程序须要访问临界资源的时候,线程首先须要获取互斥锁,当执行完成并准备退出临界区的时候,须要释放互斥锁。 对于这些状况,Python中提供了上下文管理器(Context Manager)的概念,能够经过上下文管理器来定义/控制代码块执行前的准备动做,以及执行后的收尾动做。
在Python中,能够经过with语句来方便的使用上下文管理器,
with语句能够在代码块运行前进入一个运行时上下文(执行__enter__方法),并在代码块结束后退出该上下文(执行__exit__方法)。
操做文件:with open
Flask中的离线脚本:
with app.app_context():
pass
yiled:一、一个函数中含有yield关键字,此函数为生成器,
二、生成器调用是不会当即执行,必须使用next()(结束是会报错)或send()或for调用执行
三、yield能够返回值也能够取值(生产者消费者模式)
四、调用生成器send方法传递数据时,必须先调用next(生成器)或者生成器.send(None)方法
yield from 可让生成器,直接在其余函数中调用,
互联网协议按照功能不一样分为osi七层或tcp/ip五层或tcp/ip四层
物理层:主要是基于电器特性发送高低电压(电信号),高电压1,低电压0,设备有网卡、网线、集线器,中继器,双绞线等! 单位:bit比特
数据链路层:定义了电信号的分组方式(电信号0和1没有实际意义)规定了报头(18字节)和数据 设备有:网桥、以太网交换机、网卡 单位:帧
网络层:主要功能是将ip地址翻译成对应的mac物理地址 路由 arp协议
传输层:创建端口到端口之间的通讯 tcp协议udp协议
会话层:创建客户端与服务端链接
表示层:对来自应用层的命令和数据进行解释,并按照必定的格式传送给会话层
应用层:规定应用程序的数据格式
C/S架构:
client端与server端的服务架构(客户端能够包含一个或多个在用户的电脑上运行的程序)
B/S架构:隶属于C/S架构的
Broswer端(网页端)与server端
优势:统一了全部应用程序的入口、使用方便、轻量级
三次握手:
SYC=1(创建链接) ACK(确认请求)
一、客户端(Client)向服务端(Server)发送一次请求(请求链接)
二、服务端确认并回复客户端(ACK=1, SYC=1,并在seq基础上产生一个随机数发给客户端)
三、客户端检验确认请求(ACK=1) 此时客户端与服务端就创建了链接
四次挥手:
FAN=1(断链接) ACK=1(确认请求)
一、客户端向服务端发一次请求(FAN=1)
二、服务端回复客户端 (ACK=1) (断开客户端—>服务端)
三、服务端再向客户端发请求(FAN=1) (由于有数据传输,因此二、3不能合并)
四、客户端确认请求(ACK=1) (断开服务端--->客户端)
tcp是基于链接的,必须先启动服务端,而后再启动客户端去链接服务端(三次握手,四次挥手)
udp是无链接的,先启动那一端均可以 (应用:QQ聊天) (可能会产生丢包,由于服务端不监听客户端只负责发送数据,无论客户端是否收到数据)
两个程序经过一个双向的通讯链接实现数据的交换,这个链接的一端称为一个socket
TCP协议操做:
服务器端: 客户端
建立套接字 建立套接字
绑定ip和端口 绑定ip和端口
监听 链接服务器
accept等待链接 通讯(收recv,发send)
通讯(收recv,发send)
UDP:传输速度快
不面向链接,不能保证数据的完整性
服务器端: 客户端:
建立套接字 绑定套接字
绑定ip和端口 通讯(收recvfrom,发sendto)
通讯(收recvfrom,发sendto)
粘包只会在tcp中产生,由于tcp是面向链接的、面向流(能够将多个小数据合并成一个大的数据包发送)这样以来,接收方不知道 数据包中的数据是以什么未分割数据的,就会产生粘包
而udp是无链接的、面向消息的(他不会将多个消息合并成一个大消息发送的,即便是空消息也会发送(自动加上消息头的))
两种状况:
一、发送端须要等缓冲区满才发送出去,形成粘包(发送数据时间间隔很短,数据了很小,会合到一块儿,产生粘包)
二、接收方不及时接收缓冲区的包,形成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候仍是从缓冲区拿上次遗留的数据,产生粘包)
监听多个socket是否发生变化
- select,内部循环检测socket是否发生变化;最多检测1024个socket
- poll, 内部循环检测socket是否发生变化;
- epoll, 使用回调函数的机制(自定义了三个函数)任务完成时自动调用的函数
交换机 路由器(小型交换机)
数据连接层 网络层
利用mac地址肯定传输数据的目的地 利用网关ip地址肯定传输数据的目的地
有防火墙
防火墙是内部网与外部网之间的一种访问控制设备。
它可经过监测、限制、更改跨越防火墙的数据流,尽量地对外部屏蔽网络内部的信息、结构和运行情况, 以此来实现网络的安全保护。
局域网:是指在小范围内由多台计算机互联成的计算机组 广域网:
ip和子网掩码作按位与运算,能够获得网关ip
子网掩码是用来判断任意两台计算机的IP地址是否属于同一个子网络的根据。
进程:正在执行的一个程序或者一个任务,而执行任务的是cpu
每一个进程都有本身的独立内存空间,不一样进程经过进程间通讯IPC(队列,管道)来通讯。
开进程消耗比较大,且上下文进程间的切换开销比较大,
相比线程数据相对比较稳定安全。
线程:线程是进程的一个实体,是CPU调度和分派的基本单位
线程间通讯主要经过共享内存,开线程资源开销小,上下文切换很快,但相比进程不够稳定容易丢失数据。
协程:是一种“微线程”,实际并不存在,是程序员人为创造出来的控制程序调度的(程序执行一段代码,切换执行另外一段代码)它能够实现单线程下的并发、
一、程序执行遇到IO切换,性能提升,实现了并发
二、无IO时切换,性能下降
优势:
1. 协程的切换开销更小,属于程序级别的切换,操做系统彻底感知不到,于是更加轻量级
2. 单线程内就能够实现并发的效果,最大限度地利用cpu
一、进程多与线程比较
1.线程是程序执行的最小单位,而进程是操做系统分配资源的最小单位;
2.一个进程由一个或多个线程组成,线程是一个进程中代码的不一样执行路线;
3.进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见;
4.开启进程比开线程资源开销大,线程上下文切换比进程上下文切换要快得多。由于线程共享进程内的资源
二、协程与线程进行比较
1) 一个线程能够多个协程,一个进程也能够单独拥有多个协程,这样python中则能使用多核CPU。
2) 线程进程都是同步机制,而协程则是异步
3) 协程能保留上一次调用时的状态,每次过程重入时,就至关于进入上一次调用的状态
进程是系统分配系统资源的最小单位,进程之中能够有多个线程,一个进程中的全部资源共享,进程之间资源不会共享;
线程是系统进行任务调度的最小单位,一个进程中的线程共享该进程的系统资源,线程是轻量级的进程;
协程又称微线程,轻量级线程,执行具备原子性,执行须要程序员来调用度,能够执行效率高
三、多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析
四、使用concurrent.futures开线程池和进程池
五、进程锁与线程锁
进程锁:
#加锁能够保证多个进程修改同一块数据时,同一时间只能有一个任务能够进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。 虽然能够用文件共享数据实现进程间通讯,但问题是: 1.效率低(共享数据基于文件,而文件是硬盘上的数据) 2.须要本身加锁处理 #所以咱们最好找寻一种解决方案可以兼顾:1、效率高(多个进程共享一块内存的数据)2、帮咱们处理好锁问题。这就是mutiprocessing模块为咱们提供的基于消息的IPC通讯机制:队列和管道。 1 队列和管道都是将数据存放于内存中 2 队列又是基于(管道+锁)实现的,可让咱们从复杂的锁问题中解脱出来, 咱们应该尽可能避免使用共享数据,尽量使用消息传递和队列,避免处理复杂的同步和锁问题,并且在进程数目增多时,每每能够得到更好的可获展性。
线程锁:
GIL和Lock
解决死锁问题使用递归锁(Rlock)
进程锁:为了不多个进程同时同享一个资源,加锁限制同一时间只能有一个进程修改数据,从而保证数据安全 (可使用队列和管道)
线程锁:同一时间只能一个线程访问加锁的资源,可是其余线程能够访问未加锁的资源
GIL是全局解释器锁,它的本质是一把互斥锁,将并发运行变成串行,以此来控制同一时间内共享数据只能被一个任务所修改,进而保证数据安全。(同一时刻同一进程中只有一个线程被执行)
锁的目的是为了保护共享的数据,同一时间只能有一个线程来修改共享的数据
结论:保护不一样的数据就应该加不一样的锁。
GIL 与Lock是两把锁,保护的数据不同,GIL是解释器级别的(固然保护的就是解释器级别的数据,好比垃圾回收的数据),
Lock是保护用户本身开发的应用程序的数据,很明显GIL不负责这件事,只能用户自定义加锁处理
进程池;
from concurrent.futures import ProcessPoolExecutor import time,os def piao(name,n): print('%s '%(name)) time.sleep(2) return n**3 if __name__=='__main__': p = ProcessPoolExecutor(4) objs= [] for i in range(10): obj = p.submit(piao,'sb %s'%i,i) objs.append(obj) p.shutdown(wait=True) print("主",os.getpid()) for obj in objs: print(obj.result())
from concurrent.futures import ProcessPoolExecutor import time,os def piao(name,n): print('%s is pioing %s'%(name,os.getpid())) return n**2 if __name__=='__main__': p = ProcessPoolExecutor(4) for i in range(10): res = p.submit(piao,'alex %s'%i,i).result() print(res) p.shutdown(wait=True) print('主',os.getpid())
线程池:
from concurrent.futures import ThreadPoolExecutor from threading import current_thread import time,random def task(n): print('%s is running' %current_thread().getName()) time.sleep(random.randint(1,3)) return n**2 if __name__ == '__main__': # t=ProcessPoolExecutor() #默认是cpu的核数 # import os # print(os.cpu_count()) t=ThreadPoolExecutor(3) #默认是cpu的核数*5 objs=[] for i in range(10): obj=t.submit(task,i) objs.append(obj) t.shutdown(wait=True) for obj in objs: print(obj.result()) print('主',current_thread().getName())
为每个线程开辟一块内存空间存数据
一、管道(无名管道、有名管道)
二、消息队列
三、信号量
四、信号
五、共享内存地址
六、socket
经过ip地址获取mac地址的一种协议
并发:是一种伪并行,单个cpu能够利用多道技术实现“并发”
并行:多个任务能够同时运行,多cpu才能实现
- 非阻塞:程序执行过程当中遇到IO不等待 - 代码: sk = socket.socket() sk.setblocking(False) #会报错,捕获异常 - 异步: - 经过执行回调函数:当达到某个指定的状态以后,自动调用特定函数。
把域名解析成ip :先去本地hosts文件中解析,若是没有再去DNS域名解析服务器解析
hosts:网址与ip的关系映射
建立一个缓冲区,减小了生产者与消费者这件的依赖关系、支持并发、解决了生产者快慢的问题
用户能够就近取得所需的内容,提升用户访问网站的响应速度。(解决了Internet网络拥挤的状态)
相关技术:负载均衡、缓存、动态内容分发与复制(将静态网页、图像、流媒体复制放入各个cdn中)
LVS(liunx虚拟服务器):是一个虚拟的服务器集群系统:
LVS主要用于多服务器的负载均衡。它工做在网络层,能够实现高性能,高可用的服务器集群技术
Keepalived的做用是检测服务器的状态,若是有一台web服务器宕机,或工做出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其余服务器代替该服务器的工做,当服务器工做正常后Keepalived自动将服务器加入到服务器群中,这些工做所有自动完成,不须要人工干涉,须要人工作的只是修复故障的服务器
做用:
管理LVS负载均衡软件、实现LVS集群节点的状态检查
作web架构的高可用
将请求分发到不一样的服务器上去响应,而且让每一个服务器的负载达到均衡的状态
种类:
haproxy:是一种提供高可用、负载均衡以及基于tcp或http的应用程序代理
做用:
一、nginx是一个轻量级的Web服务器(反向代理服务器、负载均衡服务器)
二、做用:
(1)保证内网的安全,可使用方向代理WAF(Web防火墙)功能,阻止web攻击(大型网站,一般将反向代理做为公网访问地址,Web服务器是内网)
(2)负载均衡,经过反向代理服务器来优化网站的负载,其特色是占有内存少,并发能力强
三、正向代理与反向代理
比喻:a(客户端)、b(代理)、c(服务端)三我的,正向代理是:a经过b向c借钱(a是知道c存在的)
反向代理是:a向b借钱,b向c借钱(a不知道c的存在)
rpc(远程过程调用):可让程序在不一样的内存空间(不一样的系统)实现远程数据通讯和互相调用
流程:客户端调用rpc接口------>rpc-------->服务端
应用场景:好比两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数或者方法,因为不在一个内存空间,不能直接调用,这时候须要经过就能够应用RPC框架的实现来解决
asynio模块能够实现异步网络操做、并发、协程
python经过gevent中的greenlet实现协程,
当一个greenlet遇到IO操做时,好比访问网络,就自动切换到其余的greenlet,等到IO操做完成,再在适当的时候切换回来继续执行。因为IO操做很是耗时,常常使程序处于等待状态,有了gevent自动切换协程,就保证总有greenlet在运行,而不是等待IO。
使用gevent实现单线程并发 爬虫(gevent中的pool或joinall) web聊天室
twisted是一个用python语言编写的事件驱动网络框架,
特色是:内部基于一个事件循环(reactor),当外部事件执行时遇到IO等待则挂起,执行下一个,IO等待完成后返回一个Deferred对象,Deferred对象会自动触发回调机制调用相应的函数处理
优缺点:关系型:容易理解(二维表结构)、支持sql复杂查询、支持事务(保持数据一致性)
非关系:数据基于键值对存储、查询速度快,数据没有耦合性、扩展性强、
innodb 支持事务(回滚)、表锁、行锁(select id,name from user where id=2 for update)
myisam 支持全文索引、表锁(- select * from user for update)
无重复列
表中属性必须依赖于主键
非主属性相关信息(关联表信息)不能依赖于主键 (消除数据冗余)
权限表、BBS、权限
注意:FK M2M
多表联查:
select * from tb1,tb2 没有where条件时,笛卡尔乘积效果
left join 以左表为基准,显示因此的内容,右表没有对应项时,显示null
select * from tb1 left join tb2 on tb1.id=tb2.id;
inner join 只显示两张表共同内容
select * from tb1 inner join tb2 on tb1.id=tb2.id;
union 显示两张表因此内容
select * from tb1 left join tb2 on tb1.id=tb2.id union select * from tb2 left join tb1 on tb1.id=tb2.id;
分组函数
select 部门ID,max(id) from 用户表 group by 部门ID having count(id)>3
group by 字段 having 判断条件 (固定语法)分组和聚合函数搭配
建立索引:
建立表+索引
create table tb( id int not null primary key
name varchar(32),
pwd varchar(32)
unique tb_pwd (pwd))
普通索引:create index tb_name on tb(name)
联合索引:create index tb_name_age on tb(name,age)
原理:B+/哈希索引 查找速度快;更新速度慢
一、索引必定是为搜索条件的字段建立的
二、innodb表的索引会存放于s1.ibd文件中,而myisam表的索引则会有单独的索引文件table1.MYI
单列:
一、普通索引 index 加速查找
二、惟一索引 unique 加速查找+不能重复
三、主键索引 primary key 加速查找+不能重复+不能为空
多列:
一、联合索引
二、联合惟一索引
三、联合主键索引
联合索引听从最左前缀原则
若是组合索引为:(name,email)
name and email -- 使用索引
name -- 使用索引
email -- 不使用索引
其它操做:
索引合并:利用多个单例索引查找
覆盖索引:在索引表中就能查到想要的数据
建立了索引,但没法命中
- like '%xx' select * from tb1 where name like '%cn'; - 使用函数 select * from tb1 where reverse(name) = 'wupeiqi'; - or select * from tb1 where nid = 1 or email = 'seven@live.com'; 特别的:当or条件中有未创建索引的列才失效,如下会走索引 select * from tb1 where nid = 1 or name = 'seven'; select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex' - 类型不一致 若是列是字符串类型,传入条件是必须用引号引发来,否则... select * from tb1 where name = 999; - != select * from tb1 where name != 'alex' 特别的:若是是主键,则仍是会走索引 select * from tb1 where nid != 123 - > select * from tb1 where name > 'alex' 特别的:若是是主键或索引是整数类型,则仍是会走索引 select * from tb1 where nid > 123 select * from tb1 where num > 123 - order by select email from tb1 order by name desc; 当根据索引排序时候,选择的映射若是不是索引,则不走索引 特别的:若是对主键排序,则仍是走索引: select * from tb1 order by nid desc;
一组sql批量执行,要么所有执行成功、要么所有失败 遵循原子性、一致性、持久性、隔离性
start transaction; 开始事务 增、删、改 update user set balance=900 where name='wsb'; #买支付100元 update user set balance=1010 where name='egon'; #中介拿走10元 update user set balance=1090 where name='ysb'; #卖家拿到90元 commit; 提交事务
rollback; 回滚
问题:如何基于数据库实现商城商品计数器?
select * from user for update
乐观锁(读)
悲观锁(写)
存储过程、视图、函数、触发器、都是保存在数据库中
触发器:在数据库中对某张表进行“增删改”时,添加一些操做
视图:一张虚拟表,根据SQL语句动态的获取数据集,并命名,下次使用时直接调用名称(只能查)
v = select * from tb where id <1000 select * from v 等同于: select * from (select * from tb where id <1000) as v
存储过程:将经常使用的sql语句命名保存到数据库中,使用时能够直接调用名称
参数有:in(入参类型) out(出参类型) inout(出入参类型)
函数:在sql语句中使用
- 聚合:max/sum/min/avg
- 时间格式化 date_format
- 字符串拼接 concat
存储过程与函数的区别:
区别:
函数 存储过程
必须有返回值 return 能够经过out、inout返回零各或多个值
不能单独使用,必须做为表达式的一部分 能够做为一个独立的sql语句执行
sql语句中能够直接调用函数 sql中不能调用过程
主键:肯定表中一条记录的惟一标识
外键:用于关联另外一张表的字段,(经过该字段肯定表中记录)
char 固定长度(255)
varchar 变长 (理论65535)
1、数学函数 ROUND(x,y) 返回参数x的四舍五入的有y位小数的值 RAND() 返回0到1内的随机值,能够经过提供一个参数(种子)使RAND()随机数生成器生成一个指定的值。 2、聚合函数(经常使用于GROUP BY从句的SELECT查询中) AVG(col)返回指定列的平均值 COUNT(col)返回指定列中非NULL值的个数 MIN(col)返回指定列的最小值 MAX(col)返回指定列的最大值 SUM(col)返回指定列的全部值之和 GROUP_CONCAT(col) 返回由属于一组的列值链接组合而成的结果 3、字符串函数 CHAR_LENGTH(str) 返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算做一个单字符。 CONCAT(str1,str2,...) 字符串拼接 若有任何一个参数为NULL ,则返回值为 NULL。 CONCAT_WS(separator,str1,str2,...) 字符串拼接(自定义链接符) CONCAT_WS()不会忽略任何空字符串。 (然而会忽略全部的 NULL)。 CONV(N,from_base,to_base) 进制转换 例如: SELECT CONV('a',16,2); 表示将 a 由16进制转换为2进制字符串表示 FORMAT(X,D) 将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若 D 为 0, 则返回结果不带有小数点,或不含小数部分。 例如: SELECT FORMAT(12332.1,4); 结果为: '12,332.1000' INSERT(str,pos,len,newstr) 在str的指定位置插入字符串 pos:要替换位置其实位置 len:替换的长度 newstr:新字符串 特别的: 若是pos超过原字符串长度,则返回原字符串 若是len超过原字符串长度,则由新字符串彻底替换 INSTR(str,substr) 返回字符串 str 中子字符串的第一个出现位置。 LEFT(str,len) 返回字符串str 从开始的len位置的子序列字符。 LOWER(str) 变小写 UPPER(str) 变大写 REVERSE(str) 返回字符串 str ,顺序和字符顺序相反。 SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len) 不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。倘若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在如下格式的函数中能够对pos 使用一个负值。 mysql> SELECT SUBSTRING('Quadratically',5); -> 'ratically' mysql> SELECT SUBSTRING('foobarbar' FROM 4); -> 'barbar' mysql> SELECT SUBSTRING('Quadratically',5,6); -> 'ratica' mysql> SELECT SUBSTRING('Sakila', -3); -> 'ila' mysql> SELECT SUBSTRING('Sakila', -5, 3); -> 'aki' mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2); -> 'ki' 4、日期和时间函数 CURDATE()或CURRENT_DATE() 返回当前的日期 CURTIME()或CURRENT_TIME() 返回当前的时间 DAYOFWEEK(date) 返回date所表明的一星期中的第几天(1~7) DAYOFMONTH(date) 返回date是一个月的第几天(1~31) DAYOFYEAR(date) 返回date是一年的第几天(1~366) DAYNAME(date) 返回date的星期名,如:SELECT DAYNAME(CURRENT_DATE); FROM_UNIXTIME(ts,fmt) 根据指定的fmt格式,格式化UNIX时间戳ts HOUR(time) 返回time的小时值(0~23) MINUTE(time) 返回time的分钟值(0~59) MONTH(date) 返回date的月份值(1~12) MONTHNAME(date) 返回date的月份名,如:SELECT MONTHNAME(CURRENT_DATE); NOW() 返回当前的日期和时间 QUARTER(date) 返回date在一年中的季度(1~4),如SELECT QUARTER(CURRENT_DATE); WEEK(date) 返回日期date为一年中第几周(0~53) YEAR(date) 返回日期date的年份(1000~9999) 重点: DATE_FORMAT(date,format) 根据format字符串格式化date值 mysql> SELECT DATE_FORMAT('2009-10-04 22:23:00', '%W %M %Y'); -> 'Sunday October 2009' mysql> SELECT DATE_FORMAT('2007-10-04 22:23:00', '%H:%i:%s'); -> '22:23:00' mysql> SELECT DATE_FORMAT('1900-10-04 22:23:00', -> '%D %y %a %d %m %b %j'); -> '4th 00 Thu 04 10 Oct 277' mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', -> '%H %k %I %r %T %S %w'); -> '22 22 10 10:23:00 PM 22:23:00 00 6' mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V'); -> '1998 52' mysql> SELECT DATE_FORMAT('2006-06-00', '%d'); -> '00' 5、加密函数 MD5() 计算字符串str的MD5校验和 PASSWORD(str) 返回字符串str的加密版本,这个加密过程是不可逆转的,和UNIX密码加密过程使用不一样的算法。 6、控制流函数 CASE WHEN[test1] THEN [result1]...ELSE [default] END 若是testN是真,则返回resultN,不然返回default CASE [test] WHEN[val1] THEN [result]...ELSE [default]END 若是test和valN相等,则返回resultN,不然返回default IF(test,t,f) 若是test是真,返回t;不然返回f IFNULL(arg1,arg2) 若是arg1不是空,返回arg1,不然返回arg2 NULLIF(arg1,arg2) 若是arg1=arg2返回NULL;不然返回arg1 7、控制流函数小练习 #7.1、准备表 /* Navicat MySQL Data Transfer Source Server : localhost_3306 Source Server Version : 50720 Source Host : localhost:3306 Source Database : student Target Server Type : MYSQL Target Server Version : 50720 File Encoding : 65001 Date: 2018-01-02 12:05:30 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for course -- ---------------------------- DROP TABLE IF EXISTS `course`; CREATE TABLE `course` ( `c_id` int(11) NOT NULL, `c_name` varchar(255) DEFAULT NULL, `t_id` int(11) DEFAULT NULL, PRIMARY KEY (`c_id`), KEY `t_id` (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of course -- ---------------------------- INSERT INTO `course` VALUES ('1', 'python', '1'); INSERT INTO `course` VALUES ('2', 'java', '2'); INSERT INTO `course` VALUES ('3', 'linux', '3'); INSERT INTO `course` VALUES ('4', 'web', '2'); -- ---------------------------- -- Table structure for score -- ---------------------------- DROP TABLE IF EXISTS `score`; CREATE TABLE `score` ( `id` int(11) NOT NULL AUTO_INCREMENT, `s_id` int(10) DEFAULT NULL, `c_id` int(11) DEFAULT NULL, `num` double DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of score -- ---------------------------- INSERT INTO `score` VALUES ('1', '1', '1', '79'); INSERT INTO `score` VALUES ('2', '1', '2', '78'); INSERT INTO `score` VALUES ('3', '1', '3', '35'); INSERT INTO `score` VALUES ('4', '2', '2', '32'); INSERT INTO `score` VALUES ('5', '3', '1', '66'); INSERT INTO `score` VALUES ('6', '4', '2', '77'); INSERT INTO `score` VALUES ('7', '4', '1', '68'); INSERT INTO `score` VALUES ('8', '5', '1', '66'); INSERT INTO `score` VALUES ('9', '2', '1', '69'); INSERT INTO `score` VALUES ('10', '4', '4', '75'); INSERT INTO `score` VALUES ('11', '5', '4', '66.7'); -- ---------------------------- -- Table structure for student -- ---------------------------- DROP TABLE IF EXISTS `student`; CREATE TABLE `student` ( `s_id` varchar(20) NOT NULL, `s_name` varchar(255) DEFAULT NULL, `s_age` int(10) DEFAULT NULL, `s_sex` char(1) DEFAULT NULL, PRIMARY KEY (`s_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of student -- ---------------------------- INSERT INTO `student` VALUES ('1', '鲁班', '12', '男'); INSERT INTO `student` VALUES ('2', '貂蝉', '20', '女'); INSERT INTO `student` VALUES ('3', '刘备', '35', '男'); INSERT INTO `student` VALUES ('4', '关羽', '34', '男'); INSERT INTO `student` VALUES ('5', '张飞', '33', '女'); -- ---------------------------- -- Table structure for teacher -- ---------------------------- DROP TABLE IF EXISTS `teacher`; CREATE TABLE `teacher` ( `t_id` int(10) NOT NULL, `t_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`t_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of teacher -- ---------------------------- INSERT INTO `teacher` VALUES ('1', '大王'); INSERT INTO `teacher` VALUES ('2', 'alex'); INSERT INTO `teacher` VALUES ('3', 'egon'); INSERT INTO `teacher` VALUES ('4', 'peiqi'); #7.2、统计各科各分数段人数.显示格式:课程ID,课程名称,[100-85],[85-70],[70-60],[ <60] select score.c_id, course.c_name, sum(CASE WHEN num BETWEEN 85 and 100 THEN 1 ELSE 0 END) as '[100-85]', sum(CASE WHEN num BETWEEN 70 and 85 THEN 1 ELSE 0 END) as '[85-70]', sum(CASE WHEN num BETWEEN 60 and 70 THEN 1 ELSE 0 END) as '[70-60]', sum(CASE WHEN num < 60 THEN 1 ELSE 0 END) as '[ <60]' from score,course where score.c_id=course.c_id GROUP BY score.c_id;
select * form tb limit 0,5
limit 起始,数量
数据量过大,页数越大,查询速度越慢,由于页数越大,数据id就越大,查询时就会从头开始扫描数据,
解决办法:
方案一:
一、记录当期页,数据ID的最大值、最小值, 二、翻页查询时,先根据数据ID筛选数据,在limit查询
select * from (select * from tb where id > 22222222) as B limit 0,10
若是用户本身修改url上的页码,咱们能够参考rest-frameword中的分页,对url中的页码进行加密处理
方案二:
能够根据实际业务需求,只展现部分数据(只显示200-300页的数据)
slow_query_log = ON 是否开启慢日志记录 long_query_time = 2 时间限制,超过此时间,则记录 slow_query_log_file = /usr/slow.log 日志文件 log_queries_not_using_indexes = ON 为使用索引的搜索是否记录
导入:mysqldump -u root -p db > F:\db.txt
导出:mysqldump -u root -p db(存在的) < F:\db.txt;
explain select * from tb; #查看sql语句执行速度
- 不用 select *
- 固定长度字段列,往前放
- char(固定长度)和varchar
- 固定数据放入内存:choice
- 读写分离,利用数据库的主从进行分离:主,用于删除、修改更新;从,查。
- 分库,当数据库中表太多,将表分到不一样的数据库;例如:1w张表
- 分表
- 水平分表,将某些列拆分到另一张表;例如:博客+博客详细
- 垂直分表,将历史信息分到另一张表中;例如:帐单
- 缓存:利用redis、memcache,将经常使用的数据放入缓存中
-查询一条数据
select * from tb where name='alex' limit 1
-text类型
为前面几个字符串建立索引
在对name作了惟一索引前提下,简述如下区别:
一、 select * from tb where name = ‘Oldboy-Wupeiqi’
二、select * from tb where name = ‘Oldboy-Wupeiqi’ limit 1 速度快
一、添加事务,
加锁
修改数据并判断是否为0
释放锁
提交事务
二、将秒杀商品放入redis中利用watch实现,
三、使用队列
处理并发:
一、前端:扩容(加机器)、 限流(限制ip访问次数)、静态化(页面最大程度使用静态,cdn)
二、后端:【内存】+【排队】