###########################################################################################
# 内 容: Python 3
# 作 者: 娜爱
# 更新日期: 2017.07.18
# 在cmd中执行py文件(路径可加双引号),如:python E:\PythonSrc\mypy_package\eg.py
###########################################################################################
1、输入函数:input(*args, **kwargs),输入结果是字符串类型。输出(打印)函数:print(*args, sep=‘ ‘, end=‘\n‘, file=None)。
2、Python数据类型都是“类(class)”类型。
dir(__builtins__):输出所有Python内置变量和函数,首字母大写的是异常名。
dir(__name__):输出Python对象的属性和方法。
3、Python提供了ord()函数获取字符的Unicode数值,chr()函数把Unicode数值转换为对应的字符。
数据类型:
(1)整型:int、bool
赋值方式:① x=99 ② x=int(99),如果是浮点数,则取整。
转换函数:int(),bin(),oct(),hex()等。
进制表示法:二进制0b,八进制0o,十六进制0x。进行二进制计算时加前缀“0b”,其他类似。
(2)浮点型:float(双精度)、complex(复数)、Decimal(定点数)
Decimal入参是整数或字符串,因为float精度不够。
(3)字符串型:str (Unicode字符构成)
使用三引号并回车,可以格式化换行输出。
使用“\”连接,可以换行书写代码。如:
s=‘abcd‘\
‘efgh‘
s.strip(c) :去除空格或指定的字符c;
s.zfill(w) :宽度小于w,用0前补;
s.join(q) :用“s”将序列“q”中的元素串起来;
“ * ”能复制字符串、列表、元组等,如s=‘#‘*9,即9个#;
s.rpartition(‘符号‘):搜索出指定符号的最右边的元素;
s.find(t) :返回t的最左位置,未找到,返回-1;
s.index(t):返回t的最左位置,未找到,返回ValueError异常;
s.ljust(w,c):左对齐,宽度w,填充符c;rjust右对齐。
s.format():格式化字符串,用{}配合使用。如‘...{0}...{1}...{2}‘.format(‘A‘,‘B‘,‘C‘) 或 ‘...{name}...{0}...‘.format(20,name=‘She‘);
format参数说明:位置参数必须在关键字参数之前,可以传字典参数。
format()可以格式规约,用冒号“:”引导规约:
‘{0:20}‘.format(s) #宽度20,默认左对齐
‘{0:<20}‘.format(s) #宽度20,左对齐
‘{0:>20}‘.format(s) #宽度20,右对齐
‘{0:^20}‘.format(s) #宽度20,中间对齐
‘{0:*>20}‘.format(s) #宽度20,右对齐,用*填充
‘{0:.4}‘.format(s) #最大宽度4,减除多余部分
‘{0:+20}‘.format(num) #对于数值num,宽度20,带符号输出
‘{0:#x}‘.format(num) #返回十六进制形式,#b二进制,#o八进制
‘{0:,}‘.format(num) #三个数字逗号分组,如银行数
‘{0:.2f}‘.format(num) #带2位小数的浮点数
‘{0:e}‘.format(num) #科学计数
(4)字节(二进制)类型:
bytes(固定的)、bytearray(可变的,可插入可删除某个字符)。
如,bin=b‘python‘ 或 ‘python‘.encode()
binarr=bytearray(bin), binarr.pop(1), binarr.insert(1,ord(‘a‘))
4、运算符“/”结果是浮点数,“//”结果是整数,“**”表幂运算。
is: 基于内存的身份比较。如,x=(‘python‘),y=(‘python‘),x is y 返回False。
比较操作符: 基于对象值比较。如,x=(‘python‘),y=(‘python‘),x == y 返回True。Python可以进行结链比较,1 <= a <= 3。
id: 获取内存地址。
in: 理解为属于,判断成员关系,val in x。
and 、or: 与、或。短运算逻辑,返回布尔值,或决定结果的操作数。
not: 非。总是返回布尔值。
del obj: 只是删除引用对象(当无任何引用对象时,数据才被回收)。
[]: 切片操作符或项目操作符。
6、ASCII编码:只有127个字符;
Unicode编码:常用的是用2个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节);
UTF-8编码:常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。
7、方法encode(‘编码格式‘):如,‘中文‘.encode(‘utf-8‘)。
8、方法decode(‘解码格式‘):如,b‘\xe6\xb1\xaa‘.decode(‘utf-8‘)。Python对bytes类型的数据用带“b”前缀的单引号或双引号表示。
9、r‘\字符‘:使转义无效。
10、#!/usr/bin/env python3
告诉Linux/OS X系统,这是一个Python可执行程序,Windows系统会忽略这个注释;
# -*- coding: utf-8 -*-
告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码。
Python文件名不能和关键字、模块名相同,否则很可能会报找不到属性的错误。
11、格式化(变量前加格式):
%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数
如,print(‘成绩增长率:%.2f‘ %(num)) #保留两位小数
12、列表(list),定义用“[]”:有序、重复,如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素,以此类推,可以获取倒数第2个、倒数第3个。
若L=[...]
print(L) #整个列表
print(*L) #用“*”拆出列表所有元素
组合类型函数,list(),tuple(),dict(),set(),frozenset()只能传入一个参数。
13、方法append():追加,obj.append(‘A‘);
方法insert():指定位置插入,obj.insert(1, ‘Jack‘);
方法pop(i) :指定位置删除,obj.pop(i),pop(0)指删除末尾,其中i是索引位置或字典的键;
方法remove():删除已知元素;
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置,如,obj.[1] = ‘Sarah‘;
14、元组(tuple),定义用“()”:有序、重复,tuple和list非常类似,但是tuple一旦初始化就不能修改,只读,更安全。
如果可能,能用tuple代替list就尽量用tuple。
最好以“,”结尾,当tuple只有一个元素时,必须以“,”结尾。
15、for <元素> in <范围>:,循环就是把每个元素代入变量x,然后执行缩进块的语句。
for _ in range(n):,使用下划线“_”,循环n次执行循环体。此时“_”作为临时性的名称使用,忽略循环计数中的实际值。
16、range(x1,x2,步长)函数,可以生成一个整数序列,长度为(x2-x1)。
17、不要滥用break和continue语句。break和continue会造成代码执行逻辑分叉过多,容易出错。
大多数循环并不需要用到break和continue语句。
18、字典(dict),定义用“{‘k‘:‘v‘}”:无序、不重复,在其他语言中也称为map,使用可哈希算法的键-值("key":"value")存储,具有极快的查找速度。字典无序。
通过in判断key是否存在,如果key不存在,可以返回false:‘Thomas‘ in d;
d.get(k,v):返回k对应的值,如果k不存在,则返回None;
d.setdefault(k,v):设置k-v键值对,如果k存在,则返回v值;
清除所有:clear(),浅拷贝:copy(),移除:pop()。
19、zip(iter1,...):依次取出每个iter元素组合成tuple,可转成list输出。如,list(zip([1,2],[‘a‘,‘b‘])) -->[(1,‘a‘),(2,‘b‘)]。
20、dict内部存放的顺序和key放入的顺序是没有关系的。
和list比较,dict有以下几个特点:
1).查找和插入的速度极快,不会随着key的增加而变慢;
2).需要占用大量的内存,内存浪费多。
而list相反:
1).查找和插入的时间随着元素的增加而增加;
2).占用空间小,浪费内存很少。
21、集合(set),定义用“set({‘v‘})”或“{‘v‘}”:无序、不重复,集合可变,但集合元素是可哈希运算的(不可变)。
添加:obj.add(‘值‘),移除:obj.remove(‘值‘),清除:obj.clear(),浅拷贝:obj.copy()。
交集:set1 & set2,并集:set1 | set2,交集之外:set1 ^ set2
固定集合(frozenset),不可变的集合。
22、“不可变对象”:str、tuple、dict、set。
“可变对象”:list。
对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。
相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。
23、如果想定义一个什么事也不做的空函数,可以用pass语句,如:
def nop():
pass
实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来以致不报错。
24、数据类型检查可以用内置函数isinstance()实现:isinstance(x,(int,float))。
25、raise TypeError(‘bad operand type‘):抛出异常信息。
26、包:必须包含一个“__init__.py”文件。
import importname[.modulename as newname] ,使用“as”能避免同名同API的包冲突。
from importname import * ,导入非私有的一切对象,使用“*”会调用该包的“__init__.py”模块中“__all__”语句。
相对导入:from ..dir import modulename。
将包或模块放入“C:\Python\Lib\site-packages”中,对所有程序都可用。
27、return(或return None),跳出函数。
函数可以同时返回多个值,但其实就是一个tuple。
28、位置参数:传参时,可以直接写值,也可以是“参数名=值”。
默认参数:可看作是单一的字典参数,必须放位置参数之后!!
定义默认参数要牢记一点:默认参数必须指向不变对象!
备注:任何参数入参时都可以用“参数名=值”的方式指定入参。
29、可变参数(类似于重载):“*nums” 表示把nums这个“list”或“tuple”的多个元素作为可变参数传进去,定义函数时往往需配用for..in..,如:
不使用可变参数则可用元组或列表:
def calc(arg),用法:calc((arg1,arg2,arg3,));
使用可变参数则可直接输入多个参数:
def calc(*arg),用法:calc(arg1,arg2,arg3)。
注意:可变参数之后的参数进行入参时,必须写“参数名=值”的形式表达。默认参数在可变参数之后!
30、字典参数(关键字参数):“ **kw ”表示把kw这个dict的所有key-value用关键字形式传入到函数的参数中,如:
def func(**kw):
print(‘keys:{0},vals:{1}‘.format(kw.keys(),kw.values()))
用法(调用时必须带上**):
extra = {‘city‘: ‘Beijing‘, ‘job‘: ‘Engineer‘,...}
func(**extra) #等价于,func(**{‘city‘: ‘Beijing‘, ‘job‘: ‘Engineer‘,...})
或者一个一个地传入键值:
func(mycity1=‘Beijing‘,mycity2=‘shanghai‘,...)。
31、命名字典参数:限制关键字参数的名字,需要一个特殊分隔符“*”,“*”后面的参数被视为命名关键字参数。
例如,只接收city和job作为关键字的参数,如:
def person(name, age, *, city, job)
函数调用时不要带上*。
32、大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以任何递归函数都存在栈溢出的问题。
控制结构。
1、if cond:
...
elif cond:
...
else: #else可选
...
if语句的简单形式:exp if condition else val
2、while cond:
...
else: #else可选,条件不满足时
...
3、for elem in iter:
...
else: #else可选,循环结束后
...
33、切片“[]”:mylist[‘开始索引‘:‘结束索引‘:‘±步长‘],“+”正向切片,“-”逆向切片。
注意:不包含结束索引的位置,如果要包含“结束索引”的值,请将“结束索引”加1。
tuple也可以用切片操作,只是操作的结果仍是tuple;
字符串也可以看成是一种list,也可以用切片操作,只是操作结果仍是字符串。
字符串翻转:str(mystr)[::-1]
34、默认情况下,“dict”迭代的是key。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()。
35、判断一个对象是可迭代:
from collections import Iterable
print(isinstance(‘12345‘,Iterable))
36、函数enumerate():可以把一个list的每个元素变成“ 序号+元素 ”对(tuple)。
37、列表生成式。
[i_exp for i in range(1, 11) if i % 2 == 0],使用[]转成列表,生成的元素放前面(表达式),后面跟for循环。可以for嵌套、if条件。
将循环结果进行了表达式运算并保存结果到列表中,直接打印出print(mylist)。
集合生成式。
{i_exp for i in range(1, 11) if i % 2 == 0},使用{}转成集合。
字典生成式。
{k_exp:v_exp for k,v in iterable if condition},使用{}转成字典。
38、生成器(generator)。创建一个生成器后,基本上不会调用next(),而是通过“ for ”循环来迭代它,并且不需关心StopIteration的错误。
第一种(类似于迭代),只要把一个列表生成式的[]改成()。不必一次性创建整个list,而是迭代生成,从而节省大量的空间。如:
gen=(i*i for i in range(1, 11) if i % 2 == 0)
第二种(类似于中断),利用关键字“yield”则变成了生成器,yield只用于函数中,遇到yield语句中断返回,再次执行时从上次返回的yield语句处继续执行。例:
#斐波拉契数列#
def fib(max):
n=0
a,b=(0,1) #利用tuple分别赋值
while n<max:
# print(b)
yield b
a,b=(b,a+b)
n+=1
for v in fib(6): #一般使用for循环输出
print(v)
#杨辉三角#
def yanghui(lines):
L=[]
n=0
while n<=lines:
yield L
L = [1] + [L[x-1] + L[x] for x in range(1,len(L))] + [1]
n+=1
for v in yanghui(10):
print(v)
39、可迭代(Iterable):凡是可作用于for循环的对象都是Iterable类型;
迭代器(Iterator):凡是可作用于“next()”函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
可迭代的类型有:list、tuple、dict、set、str等。
可以通过iter()函数获得一个迭代器(Iterator)对象。
40、高阶函数:把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。
41、函数map(函数f,Iter):即映射,函数f接收两个参数,一个是函数名,一个是可迭代的定义域集合(Iterable)。结果是个迭代器(Iterator)。
42、函数reduce(函数f,Iter):函数f(arg1,arg2),该函数f返回的结果又作为arg1,这样的函数f作用在Iter元素上进行累积计算。如,
from functools import reduce
def f(arg1,arg2):
return arg1*arg2
def prod(ls):
res=reduce(f,ls)
return res
print(prod([10,2,4,5]))
43、函数filter(函数f,Iter):过滤。函数f作用在Iter元素上,若函数f返回True则留下该Iter的元素,若返回False则滤除掉该Iter的元素。
44、函数sorted(Iter,<key=函数名>,<reverse=False>):排序。可以通过函数完成自定义排序,该函数作用在Iter元素上。如:
sorted({‘d‘:4,‘b‘:2,‘a‘:1,‘c‘:3}, key=lambda e:e[0], reverse=False) #e[0]自动迭代,按键排序
45、一个函数可以返回一个计算结果,也可以返回一个函数。
返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。
46、当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数(λ)更方便。
lambda 参数: 表达式。如,lam = lambda x: x**2,则可显式调用lam(3)=9。
sorted.L(key=lambda ele: abs(ele)),隐式调用,会自动将列表L每个元素传入ele。
47、偏函数:当函数的参数个数太多,需要简化时,使用“functools.partial”可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。如:
int2 = functools.partial(int, base=2)
48、模块:一个.py文件就称之为一个模块。最大的好处是大大提高了代码的可维护性。
导入模块:“ from 包名 import 模块名 ”。
49、if __name__==‘__main__‘:
test()
这句话表示,仅当直接执行本模块时,执行if代码块。当其他模块调用此模块时,则忽略该代码块。
50、类是抽象的模板,实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。
class Student(object):
def __init__(self): #重写object中__init__()方法初始化。可用super().__init__()调用父类的__init__()初始化。
pass
pass
class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是继承类(默认为object,在builtins.py模块中第720行~820行),表示该类是从哪个类继承下来的。
“self”一般用在类方法中,表示只有实例对象能访问,而类对象不能访问。作用:调用自身(实例)的属性或方法。
类方法外部的属性,类对象可以访问,而实例对象不能访问。
实例对象:stu=Student([args]),自动进行了两个步骤,首先调用__new__()方法创建实例对象,然后调用__init__()初始化。
Python要么是public要么就是private,一般要避免下划线的使用。
以单下划线开头(_foo):视为受保护的成员,视为不要在外部使用;
以双下划线开头的(__foo):真正的私有成员,只能在类自己内部中使用;
以双下划线开头和结尾的(__foo__):特殊方法专用的标识,如 __init__()构造函数。这类特殊方法可以重定义,但不是同名调用,而是使用操作符或调用去掉双“__”的方法。
51、多态:一个类的实例可以是该类的类型,也可以是父类的类型,但不可以是其子类的类型。
52、对于静态语言(例如Java)来说,如果需要传入Animal类型,则传入的对象必须是Animal类型或者它的子类,否则,将无法调用其中的方法。
对于Python这样的动态语言(“鸭子语言”:如果某个对象调用某个方法,就不必管该对象属于哪个类,只要存在需要调用的方法即可)来说,
则不一定需要传入Animal类型,我们只需要保证传入的对象有其方法就可以了。
53、方法type(数据参数):返回数据类型。
54、函数与方法区别:
方法(类的)调用方式: 对象.方法名()
函数调用方式: 函数名(对象)
方法的第一个参数是自调参数(self),函数没有自调参数。
55、函数getattr(对象/类名,属性名):获取对象/类名属性;
函数setattr(对象/类名,属性名):设置对象/类名属性;
函数hasattr(对象/类名,属性名):判断对象/类名属性是否存在。
56、动态添加(绑定)属性:
“对象名.新属性名” = “值” , 此方式添加的属性只对该实例对象有效;
“类名.新属性名” = “值” , 此方式添加的属性对所有实例对象有效;
“动态”缺点:无法做属性检查,而自定义的“getter()”和“setter()”可以做参数的检查,如判断等。
57、动态添加(绑定)方法:
“对象名.新方法名” = “已定义函数名” , 此方式添加的方法只对该实例对象有效;
“类名.新方法名” = “已定义函数名” , 此方式添加的方法对所有实例对象有效;
58、变量__slots__=(‘属性1‘,‘属性2‘,...):限制类属性,对象只能访问和添加的属性。但对继承的子类是不起作用的。
hasattr(object, name):
判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。
getattr(object, name[,default]):
获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
setattr(object, name, values):
给对象的属性赋值,若属性不存在,先创建再赋值。
59、@property 属性装饰器:把取值、赋值(getter()、setter())方法变成属性,则可以通过“obj.__attr”取值,通过“obj.__attr=val”赋值(最好使用私有属性)。
@property 属性装饰器广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,如判断等,这样,程序运行时就减少了出错的可能性。
例:
class Money:
def __init__(self, dollars, cents):
self.__total_cents = dollars * 100 + cents
#直接使用@property,取值-->obj.cents,相当于obj.getter()
@property
def cents(self):
return self.__total_cents % 100;
#使用@方法名.setter,赋值-->obj.cents=val,相当于obj.setter()
@cents.setter
def cents(self, new_cents):
self.__total_cents = 100 * self.dollars + new_cents
#实例
m=Money(1,1)
m.cents #取值
m.cents=2 #赋值
@classmethod 类方法装饰器(classname.classmethod)。
60、MixIn:在设计类的继承关系时,通常,主线都是单一继承下来的,如果需要“混入”额外的功能,通过多重继承就可以实现,这种设计通常称之为MixIn(混合)。
61、动态创建类:
myclass=type(‘MyClass‘,(object,),{‘func‘:exfn})
说明:‘MyClass‘:类名;
(object,):继承类,用tuple;
{‘func‘:exfn}:类方法,dict型,其中exfn是外部定义好的方法。
62、捕获异常
try:
pass
except Exception as e: #尽量指定精确的异常类
pass
raise #可以在这里抛出异常,让上层调用者处理。程序不会往下执行。如果没有抛出,程序会继续往下执行。
else: #可选,try正常结束后
pass
finally: #可选,总是被执行
pass
当认为某些代码可能会出错时,就可以用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,
即except语句块,执行完except后,如果有finally语句块(非必需),则执行finally语句块,至此,执行完毕。
所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”。
错误和异常:
错误,机器出现的错误不需要处理。
异常,程序运行而能自动识别的异常,一般要捕获处理(立即处理或上抛给调用者)。系统异常与逻辑异常。
63、如果要打印错误追踪,导入logging,如:
import logging
...
except Exception as e:
logging.exception(e) #不需要print(),直接输出错误日志追踪。
64、抛出异常
a、raise Exception(‘str‘)
b、raise # raise语句如果不带参数,就会把当前错误原样抛出给调用者。
65、调试。
(1)使用assert语句。面向开发者设计,用于程序的调试。
凡是用print()来辅助查看的地方,都可以用断言(assert)来替代。
assert 表达式,‘输出提示‘ ,其中,若“表达式”为假,程序终止,并给出“输出提示”;为真,程序继续执行,无输出提示。
(2)使用logging语句,服务端写入日志,还可以通过http get/post,socket,email写入日志。
import logging
logging.basicConfig(level=logging.INFO) #有debug,info,warning,error等几个级别
...
logging.info()
66、闭包:如果外部函数里有内部函数,内部函数对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
装饰器就是一种闭包!
调用外部函数传递的参数就是自由变量。
简单说,闭包就是根据不同的配置信息得到不同的结果。
用途1:当闭包执行完后,仍然能够保持住当前的运行环境。(类似静态变量)
用途2:闭包可以根据外部作用域的局部变量来得到不同的结果。(这有点像一种类似配置功能的作用,我们可以修改外部的变量,闭包根据这个变量展现出不同的功能。)
如:
def exfunc(x):
def clofunc(y):
return x + y
return clofunc
调用:f=exfunc(6) # x=6,返回了内部函数clofunc赋给f,即此时调用内部函数。
print(f(8)) # y=8
67、装饰器(decorator):使用@调用装饰器。在不更改原函数的情况下,该函数被调用前,扩展该函数功能。
故装饰器以函数入参,并返回内部函数。例:
def deco(func): #装饰器函数
def wrapper(*args,**kw): # “*args,**kw”,表示可接收任何参数
print(‘调用了%s()‘ % func.__name__)
return func(*args,**kw) #返回入参函数
return wrapper #返回内部函数,闭包。
@deco
def now():
print(‘2017-5-4‘)
68、IO:涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。
从磁盘【读】文件到内存,就只有【Input】操作,反过来,把数据【写】到磁盘文件里,就只是一个【Output】操作。
现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符)。
69、读文件。
如果文件很小,read()一次性读取最方便;如果不能确定文件大小,反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便。
无论读写,都先打开(open)文件的路径,即入口。
例:try:
f=open(‘D:\Personal\Desktop\PyNote.py‘,‘r‘) #先打开文件
print(f.read()) #一次性全部读取
except IOError as e:
print(‘读入文件出错‘,e,sep=‘||‘)
finally:
f.close() #无论如何需要关闭流
*推荐使用:另一种简洁读文件方法(不必调用close()方法),使用with语句操作文件IO是个好习惯:
with open(‘D:\Personal\Desktop\PyNote.py‘,‘r‘) as file:
print(file.read())
70、写文件。
当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。
只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。
忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险,例:
*推荐使用:
with open(‘D:\Personal\Desktop\PyNote1.txt‘,‘w‘) as file:
file.write(‘写文件!‘) #返回字符长度
71、字符流(StringIO)。StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口。流必须先读出来再写入文件中。
from io import StringIO,并先创建一个StringIO实例。以下例1、2均可用getvalue()方法获取流。
例1:使用write()写入流中。
f=StringIO() #创建一个StringIO实例
f.write(‘字符流IO‘)
print(f.getvalue()) #用getvalue()方法获取流。
#write()结束后指针在末尾,使用方法tell()能知道指针位置,所以read()方法读取不到。
#除非用方法seek(i)将指针定位开始位置,则可以用read()方法读取。
例2:初始化流,用read()方法读取流。
f = StringIO(‘Hello!\nHi!\nGoodbye!‘) #初始化流,指针在开头
while True:
s = f.readline() #可用read()方法读取流
if s == ‘‘:
break
print(s.strip()) #strip()去除首尾空格
72、字节流(BytesIO)。类似于字符流。以下例1、2均可用getvalue()方法获取流。
例1:使用write()写入流中。
from io import BytesIO
b=BytesIO() #创建一个BytesIO实例
b.write(‘字节流‘.encode())
print(b.getvalue()) #用getvalue()方法获取流。
#write()结束后指针在末尾,使用方法tell()能知道指针位置,所以read()方法读取不到。
#除非用方法seek(i)将指针定位开始位置,则可以用read()方法读取。
例2:初始化流,用read()方法读取流。
b=BytesIO(‘字节流‘.encode()) #初始化流,指针在开头
print(b.read()) #可用read()方法读取流
73、操作目录或文件:导入os包,import os (当前路径 sys.argv[0])
(1)创建目录:os.mkdir(‘路径‘)
(2)删除目录:os.rmdir(‘路径‘)
(3)目录列表:os.listdir(‘路径‘)
(4)产生一个当前绝对路径的字符串:os.path.abspath(‘name‘),其中的name也可以是指定的完整路径。当name是“.”表示当前完整目录。
(5)拼接路径(处理不同操作系统路径规则):os.path.join(‘D:\Personal‘,‘mydir‘)
(6)拆出一个路径的末尾:os.path.split(‘D:\Personal\Desktop\mydir.py‘),-->结果是(‘D:\\Personal\\Desktop‘, ‘mydir.py‘)
(7)拆出扩展名:os.path.splitext(‘D:\Personal\Desktop\mydir.py‘),-->结果是(‘D:\\Personal\\Desktop\\mydir‘, ‘.py‘)
返回文件名(含扩展名):os.path.basename(‘D:\Personal\Desktop\mydir.py‘),-->结果是‘mydir.py‘
(8)文件最后修改时间戳:os.path.getmtime(‘路径‘)
(9)目录树:os.walk(‘路径‘)
解压与压缩(import gzip)。
解压(读):
f = gzip.open(‘file.txt.gz‘, ‘rb‘) #打开解压路径
file_content = f.read() #直接解压
f.close()
压缩(写):
air=open(‘Air.xml‘)
fh=StringIO(air.read()) #字符流缓存
airzip=gzip.open(‘AirZip.xml.gz‘,‘wb‘) #打开压缩路径
airzip.write(fh.getvalue().encode()) #直接压缩
air.close()
airzip.close()
74、(1)序列化(pickling):把对象转成字节(持久化二进制文件)。经常遇到在Python程序运行中得到了一些字符串、列表、字典等数据,
想要长久的保存下来,方便以后使用,而不是简单的放入内存中关机断电就丢失数据。它可以将对象转换为一种可以传输或存储的格式。如:
import pickle
1)序列化:
pickle.dumps(obj) #注意是生成字节byte,dumps()
2)dump(),序列“写入”文件中:
file=open(‘D:\Personal\Desktop\mypy.txt‘,‘wb‘) #‘wb‘,以字节写入
pickle.dump(obj,file,protocol=0) #序列并写入,dump(),不带字母“s”的方法与文件相关。protocol=0 为ASCII,1是旧式二进制,2是新式二进制协议
file.close()
3)load(),反序列“读取”:
file=open(‘D:\Personal\Desktop\myp1y.txt‘,‘rb‘) #‘rb‘,以字节读取
pickle.load(file) #反序列,load()
file.close()
序列化的缺点:1.只能用于Python,并且可能不同版本的Python彼此都不兼容。2.不安全。
(2)struct结构体:类似C语言的结构体,包含不同类型的数据。将特定的结构体类型打包成字节型数据(二进制流)然后再网络传输,
而接收端也应该可以通过某种机制进行解包还原出原始的结构体数据。网络通信当中,大多传递的数据是以二进制流存在的。
import struct #打包方法:pack(fmt,values)
bin_data = struct.pack(‘>i3sf‘, 1, b‘abc‘, 2.7) #按格式打包成字节,“>”字节顺序,“i”32位整型,“3s”长度为3的字符串,“f”浮点型。
print(bin_data) #字符串需要转成字节,且指定长度。
struct.unpack(‘>i3sf‘,bin_data) #解包还原,返回元组
或:
strc=struct.Struct(fmt) #初始化打包/解包格式fmt
strc.pack(data)
strc.unpack(bin_data)
75、JSON序列转化(一定是双引号格式)。导入json模块。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
import json
json.dumps(dic_obj) #dic_obj是字典类型
JSON反序列:
json_str=‘{"name":"wcw","addr":"bj"}‘ #注意用单引号包起来
inv_json=json.loads(json_str)
print(inv_json) #结果是字典
类对象的JSON序列:
stu=Student(‘wcw‘,20,100) #实例
json.dumps(stu.__dict__) #用内置属性__dict__
或者 json.dumps(stu,default=lambda obj:obj.__dict__)
76、进程。任何进程默认就会启动一个线程,我们把该线程称为主线程。
对于操作系统来说,一个任务就是一个进程(Process)。有些进程还不止同时干一件事,把进程内的这些“子任务”称为线程(Thread)。
线程是最小的执行单元,而进程由至少一个线程组成。
获取操作系统的进程ID:import os 然后 os.getpid()。
(1)创建一个进程。需要导入模块:from multiprocessing import Process,实例一个进程类。
if __name__==‘__main__‘:
p=Process(target=‘子进程名‘,arg=(‘子进程的参数‘,)) #实例一个子进程,target传入函数,arg是元组。
p.start() #运行进程
p.join() #等待子进程结束后再继续往下运行
(2)如果要启动大量的子进程,可以用“进程池”的方式批量创建子进程。需要导入模块:from multiprocessing import Pool。
if __name__==‘__main__‘:
p=Pool(3) #实例子进程池,参数3表示可同时进行3个子进程
p.apply_async(func=task,args=(i,)) #运行进程池,func传入函数,arg是元组
p.close() #调用join()之前必须先调用close()
p.join() #等待子进程结束后再继续往下运行
77、进程通信:Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。例:
def write(que): #写的程序
print(‘调用写进程%s‘ %os.getpid())
for val in [‘AA‘,‘BB‘,‘CC‘,‘DD‘]:
print(‘把%s放入Queue中‘ %val)
que.put(val)
time.sleep(random.random())
def read(que): #读的程序
print(‘调用读进程%s‘ %os.getpid())
while True:
val=que.get()
if val==‘ ‘:
break
print(‘从Queue中读出%s‘ %val)
time.sleep(random.random())
if __name__==‘__main__‘:
que=Queue() #实例一个通信列队,并传给各个子进程
proc_write=Process(target=write,args=(que,)) #写的子进程
proc_read=Process(target=read,args=(que,)) #读的子进程
proc_write.start()
proc_read.start()
proc_write.join()
proc_read.terminate() #在这里读进程是死循环,方法terminate()强制终止。
print(‘the end‘)
78、线程。
Python的标准库提供了两个模块:_thread和threading。_thread是低级模块,threading是高级模块,绝大多数情况下,只使用threading这个高级模块。
import threading
print(‘当前线程:%s‘ %threading.current_thread())
thr=threading.Thread(target=函数名,name=‘自定义线程名‘,args=(‘函数参数‘,)) #实例一个线程
thr.start()
thr.join()
线程锁:多线程和多进程最大的不同在于,多进程中,同一个变量,互不影响;而多线程中,所有变量都由所有线程共享,所以,
线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。
Python解释器由于设计时有全局锁(GIL),导致了多线程无法利用多核。
例:
lock = threading.Lock() # 先要获取锁
lock.acquire()
try:
tread_func() #对线程调用的函数上锁
finally:
lock.release() #改完了一定要释放锁,否则那些等待锁的线程将永远等待下去,成为死锁
79、ThreadLocal应运而生,不用查找dict(这是定义全局的dict,key作为某个Thread,value作为属性),ThreadLocal帮你自动做这件事。
ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,
这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。例:
import threading
local_school = threading.local() #实例一个ThreadLocal对象,用于封装属性,并能保证多线程使用该属性而不互相干扰
#线程调用的方法
def thread_student_func(name, age, score):
local_school.name = name #封装属性
local_school.age = age
local_school.score = score
thread_student()
def thread_student():
name = local_school.name #读取TreadLocal属性
age = local_school.age
score = local_school.score
print(‘name:%s,age:%d,score:%0.1f‘ % (name, age, score), threading.current_thread().ident)
thr1 = threading.Thread(target=thread_student_func, args=(‘汪春旺‘, 25, 99.5))
thr2 = threading.Thread(target=thread_student_func, args=(‘娜娜‘, 20, 90))
thr1.start()
thr2.start()
thr1.join()
thr2.join()
80、进程 VS 线程。
要实现多任务,通常我们会设计Master-Worker模式,Master(主进程/线程)负责分配任务,Worker(子进程/线程)负责执行任务
进程优点:稳定性高,因为一个子进程崩溃了,不会影响主进程和其他子进程。
进程缺点:耗CPU和内存。
线程优点:效率高。
线程缺点:任何一个线程挂掉都可能直接造成整个进程崩溃,因为所有线程共享进程的内存。
任务分为计算密集型和IO密集型。
计算密集型(C语言)任务主要消耗CPU资源。IO密集型(Python语言)任务主要涉及到网络、磁盘IO。
在Thread和Process中,应当优选Process,因为Process更稳定,而且,Process可以分布到多台机器上,而Thread最多只能分布到同一台机器的多个CPU上。
分布式进程:Python的multiprocessing模块不但支持多进程,其中managers子模块还支持把多进程分布到多台机器上。
81、正则表达式,需导入re模块。强烈建议使用Python的“r”前缀,就不用考虑转义的问题。
字符:
\d 匹配一个数字
\w 匹配一个数字或字母
. 匹配任意字符
\字符 匹配某个指定字符,或者直接写该字符
\s 匹配一个空格
数量:
* 任意个
+ 至少一个
? 0个或一个
{n} n个
{n,m} n~m个
指定字符范围用[-]:
[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线
| 或
^ 行的开头,^\d表示必须以数字开头,最好每次都带上
$ 行的结束,\d$表示必须以数字结束,最好每次都带上
用正则表达式切分字符串比用固定的字符更灵活,如:
re.split(r‘\s+‘, ‘a b c‘) #必须是re包的split()方法。以一个或多个空格切分。
正则表达式分组:用“()”表示的就是要提取的分组,方法group()获取某一个分组,groups()获取所有分组。
正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。加问号“?”可以去除贪婪匹配。如:re.match(r‘^(\d+?)(0*)$‘, ‘102300‘).groups()
82、几个常用的内置模块。
(1)datetime日期时间模块。
from datetime import datetime
datetime.now().hour #获取当前日期时间
datetime(2017,5,20,13,14,0) #指定日期时间,返回datetime对象
时间戳(timestamp)一旦确定,其UTC(时区)时间就确定了。
如果要存储datetime,最佳方法是将其转换为时间戳(timestamp)再存储,因为时间戳与时区完全无关。时间戳是一个浮点数。
datetime.timestamp(‘datetime对象‘) #日期时间-->时间戳,若是字符串需要把字符串转成datetime对象
datetime.fromtimestamp(‘戳‘) #时间戳-->日期时间
datetime.strptime(‘2017-5-21‘,‘%Y-%m-%d‘) #字符串-->日期时间 (常用,注意参数的分隔符一致即可)
datetime.strftime(now,‘%Y-%m-%d %H:%M:%S‘) #日期时间-->字符串
日期时间的加减,需要导入timedelta这个类。
now+timedelta(hours=1)
时区(UTC):from datetime import datetime,timedelta,timezone
utc_curr=datetime.utcnow().replace(tzinfo=timezone.utc) #utcnow() 返回当前时区,replace() 替换成默认时区UTC
bj_utc=datetime.astimezone(utc_curr,timezone(timedelta(hours=8))) #astimezone() 转换成指定时区
(2)collections集合模块。
1、namedtuple(type_name,field_name):命名的元组。将“type_name”视为表名,“field_name”视为字段名。如:
point = namedtuple(‘poi‘,‘x , y‘)
p = point(‘abc‘,‘100‘) #赋值
print(p.x, p.y) #取值
2、deque(iterable):双队列。为了高效实现插入和删除操作的双向列表list,适合用于队列和栈。因为list是线性存储,数据量大的时候,插入和删除效率很低。
deque除了实现list的append()和pop()外,还支持appendleft()和popleft()。
3、defaultdict(default_func):使用dict时,如果引用的Key不存在,就会抛出KeyError。如果希望key不存在时,返回一个默认值,就可以用defaultdict。如:
def_dic = defaultdict(lambda:‘none‘)
def_dic[‘k1‘] = ‘a1‘
4、OrderedDict类:使用dict时,Key是无序的,如果要保持Key的顺序,可以用OrderedDict,如:
orddic=OrderedDict({‘1‘:‘a‘,‘2‘:‘b‘,‘3‘:‘c‘})
5、Counter类:是一个简单的计数器,例如,统计字符出现的个数。
c=Counter()
for t in ‘wangchunwang‘:
c[t]=c[t]+1
print(c.most_common())
6、heapq:堆。会自动排序。
heap=[]
heapq.heappush(heap,(2,‘two‘))
heapq.heappush(heap,(1,‘one‘))
(3)base64模块:对二进制数据编码,避免显示乱码(用记事本打开exe、jpg、pdf这些文件时,我们都会看到一大堆乱码);
Base64是把3字节一组变为4字节一组,所以,Base64编码的长度永远是4的倍数;
base64是一种任意二进制到文本字符串的编码方法,常用于在URL、Cookie、网页中传输少量二进制数据。
base64.b64encode(b‘‘) #编码
base64.b64decode(b‘‘) #解码
base64.urlsafe_b64encode(b‘‘) #对于URL二进制编码时,把字符+和/分别变成-和_
base64.urlsafe_b64decode(b‘‘)
(4)hashlib哈希算法模块(加密函数)
1、hashlib.md5()。MD5是最常见的摘要算法,速度很快,生成结果是一个32位的十六进制字符串表示。如:
import hashlib
md5=hashlib.md5(‘how to use md5 in python hashlib?‘.encode())
print(md5.hexdigest())
2、hashlib.shal()。与md5()用法一致。
(5)itertools模块:操作可迭代对象,返回值不是list,而是Iterator,只能用“for”循环迭代的时候才真正计算。
1、count类。无限计数。
2、cycle类。无限循环每个元素。
3、repeat类。重复整个参数。
4、chain类。将迭代对象串联。
5、groupby类。把迭代器中相邻的重复元素挑出来放在一起。
(6)contextlib模块:上下文。
@contextmanager,上下文装饰器。
(7)关于XML。
操作XML有两种方法:DOM和SAX。
DOM方法会把整个XML读入内存,解析为树,因此占用内存大,解析慢,优点是可以任意遍历树的节点。
SAX方法是流模式,边读边解析,占用内存小,解析快,缺点是我们需要自己处理事件。
正常情况下,优先考虑SAX,因为DOM实在太占内存。
ElementTree模块:XML元素树,解析和写入节点。
tree=ElementTree() #实例元素树
root=tree.parse(fh) #获取根节点
print(root)
stations=set({})
for ele in tree.getiterator(‘station_name‘): #迭代某个节点
stations.add(ele.text)
(8)关于HTMLParser。
HTML本质上是XML的子集,但是HTML的语法没有XML那么严格,所以不能用标准的DOM或SAX来解析HTML。Python提供了HTMLParser来非常方便地解析HTML。
(9)urllib模块:用于操作URL地址(属于上下文,所以可以用 with...as... 语句)。
request子模块,Request类。
1、GET
请求指定的网址:with urlopen(‘https://api.douban.com‘) as url:
print(url.status,url.reason)
print(url.getheaders())
模拟浏览器,添加HHTP头:req = Request(‘http://www.douban.com/‘, headers={‘User-Agent‘: ‘Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25‘})
with urlopen(req) as url:
print(url.getheaders())
print(url.read().decode())
2、POST
如果要以POST发送一个请求,只需要把urlopen()中参数data以bytes形式传入。
email=input(‘微博账号:‘)
passwd=input(‘密码:‘)
login_info=parse.urlencode({
‘username‘:email,
‘password‘:passwd,
‘entry‘: ‘mweibo‘,
‘client_id‘: ‘‘,
‘savestate‘: ‘1‘,
‘ec‘: ‘‘,
‘pagerefer‘: ‘https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F‘
})
req=Request(‘https://passport.weibo.cn/sso/login‘)
req.add_header(‘Origin‘, ‘https://passport.weibo.cn‘)
req.add_header(‘User-Agent‘, ‘Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25‘)
req.add_header(‘Referer‘, ‘https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F‘)
with urlopen(req,data=login_info.encode()) as url:
print(url.status,url.read())
83、第三方库。基本上,所有的第三方模块都会在PyPI-the Python Package Index上注册,只要找到对应的模块名字,即可用“pip install modulename”或“easy_install modulename”安装。
(1)pillow,图像处理库。
在命令行cmd直接输入:pip install pillow 进行安装。例,制作验证码:
from PIL import Image #导入pillow
def rand_draw_color():
return (random.randint(64,255),random.randint(64,255),random.randint(64,255))
def font_color():
return (random.randint(32,255),random.randint(32,255),random.randint(32,255))
def rand_char():
return chr(random.randint(65,90))
#图像的尺寸
width=60*4
height=60
#创建图像
img=Image.new(‘RGB‘,(width,height),color=(255,255,255))
#创建画布(用于涂鸦)
draw=ImageDraw.Draw(img)
#填充画布颜色,按像素填充
for draw_color_x in range(width):
for draw_color_y in range(height):
draw.point((draw_color_x,draw_color_y),fill=rand_draw_color())
#输出4个随机字符
for char_count in range(4):
draw.text((60*char_count+15,10),rand_char(),fill=font_color(),font=ImageFont.truetype(‘Font/msyh.ttf‘,36))
#模糊处理
img=img.filter(ImageFilter.GaussianBlur) #这里必须做赋值处理
img.save(‘Images/vali_code.jpg‘,‘JPEG‘)
(2)virtualenv为应用提供了隔离的Python运行环境,解决了不同应用间多版本的冲突问题。
84、图形界面(GUI),调用内置的Tkinter。。例:
from tkinter import *
class AppTK(Frame):
def __init__(self):
super().__init__()
def createWidg(self):
self.nameInput=Entry()
self.nameInput.pack()
self.alertButt=Button(text=‘确定‘,command=self.alertFunc)
self.alertButt.pack()
def alertFunc(self):
info=self.nameInput.get() or ‘空值‘
messagebox.showinfo(‘消息‘,‘欢迎,‘+info)
app=AppTK()
app.createWidg()
app.master.title(‘提示‘)
app.mainloop()
85、网络编程。
IP地址实际上是一个32位整数(称为IPv4),以字符串表示的IP地址如192.168.0.1实际上是把32位整数按8位分组后的数字表示,目的是便于阅读。
IPv6地址实际上是一个128位整数,它是目前使用的IPv4的升级版,以字符串表示类似于2001:0db8:85a3:0042:1000:8a2e:0370:7334。
TCP协议则是建立在IP协议之上的。TCP协议负责在两台计算机之间建立可靠连接,保证数据包按顺序到达。
端口有什么作用?在两台计算机通信时,只发IP地址是不够的,因为同一台计算机上跑着多个网络程序。
(1)TCP协议编程。使用import socket。创建TCP连接时,主动发起连接的叫客户端,被动响应连接的叫服务器。
80端口是Web服务的标准端口。SMTP服务是25端口,FTP服务是21端口,等等。端口号小于1024的是Internet标准服务的端口,端口号大于1024的,可以任意使用。
备注:发送和接收的数据是字节,需要编码和解码。
客户端:必须知道服务器的IP地址和端口号。
#建议网络连接
sock=socket()
sock.connect((‘www.sina.com.cn‘,80))
sock.send(b‘GET/ HTTP/1.1\r\nHost:www.sina.com.cn\r\nConnection:close\r\n\r\n‘) #注意HTTP协议格式
#接收数据,使用永循环
buffer=[]
while True:
data=sock.recv(1024)
if data:
buffer.append(data)
else:
break
data=b‘‘.join(buffer)
sock.close()
#保存内容
header, html = data.split(b‘\r\n\r\n‘, 1)
print(header.decode(‘utf-8‘))
with open(‘sina.html‘, ‘wb‘) as f:
f.write(html)
服务器:服务器进程首先要绑定一个端口并监听来自其他客户端的连接。
#####服务器端#####
#1.建立连接,绑定服务器
so_server=socket(type=SOCK_STREAM) #type=SOCK_STREAM表示TCP协议
so_server.bind((‘127.0.0.1‘,9999))
so_server.listen(5) #监听端口,入参数指定等待连接的最大数量
print(‘等待连接...‘)
#3.接收客户端连接的函数,使用永循环
def tcp_link(so_link,addr_link):
print(‘正在连接‘,addr_link)
so_link.send(‘欢迎!‘.encode()) #向客户端发送send()
while True:
data=so_link.recv(1024) #接收客户端数据recv()
if not data or data.decode()==‘exit‘:
break
so_link.send(‘你好,%s‘.encode() %data)
so_link.close()
print(‘关闭连接‘, addr_link)
#2.服务器通过一个永久循环来接受客户端的连接
while True:
so,addr=so_server.accept() #接受客户端连接
thr=Thread(target=tcp_link, args=(so, addr)) #线程处理连接
thr.start()
thr.join()
#####客户端#####
from socket import socket
so_client=socket(type=SOCK_STREAM)
so_client.connect((‘127.0.0.1‘,9999)) #连接服务器
print(so_client.recv(1024).decode()) #接收服务器“欢迎”数据。如果数据大,则采用缓存append
for data in [‘Michael‘, ‘Tracy‘, ‘Sarah‘]: #向服务器发数据,并接收返回数据
so_client.send(data.encode())
print(so_client.recv(1024).decode())
so_client.send(‘exit‘.encode())
so_client.close()
(2)UDP协议编程。UDP是面向无连接的协议,不可靠。优点是和TCP比,速度快。
服务器不需要监听(listen()),客户端不需要连接(connect())。
#####服务器端#####
so=socket(type=SOCK_DGRAM)
so.bind((‘127.0.0.1‘,9999))
def udp_accept():
while True:
data,addr=so.recvfrom(1024)
print(‘请求客户端:‘,addr)
so.sendto(‘你好,%s‘.encode() %data,addr)
thr=Thread(target=udp_accept)
thr.start()
thr.join()
#####客户端#####
so=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
for data in [‘Michael‘, ‘Tracy‘, ‘Sarah‘]:
so.sendto(data.encode(),(‘127.0.0.1‘,9999))
print((so.recv(1024)).decode())
so.close()
86、发邮件协议:“SMTP”:Simple Mail Transfer Protocol
收邮件协议:“POP3”:Post Office Protoco
“IMAP”:Internet Message Access Protocol
87、数据库编程。
关系型:闭源收费数据库:Oracle、DB2; 开源免费数据库:MySQL、SQLite(嵌入式数据库,轻量,Python内置)
1、SQLite
#连接数据库,若无则新建
conn=sqlite3.connect(‘test.db‘)
#创建游标,实际操作者
cursor=conn.cursor()
cursor.execute(sql) #执行query
cursor.close() #关闭游标
conn.commit() #执行insert等操作后要调用commit()提交事务
conn.close() #关闭连接
2、MySQL
cmd安装驱动:pip install pymysql, 例:
import pymysql
conn=pymysql.connect(user=‘root‘, password=‘0000‘, database=‘test‘,charset=‘utf8‘)
cursor=conn.cursor()
sql=‘select * from USER ‘
cursor.execute(sql)
data=cursor.fetchall()
print(data)
cursor.close()
conn.close()
3、MySQL框架:SQLAlchemy,把关系数据库的表结构映射到class对象上(即ORM技术)。安装SQLAlchemy:pip install sqlalchemy。例:
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
Base=declarative_base() #先创建基类
class Pers(Base): #表的映射类
__tablename__=‘person‘ #表名
id=Column(primary_key=True) #要知道主键
name=Column()
engine=create_engine(‘mysql+pymysql://root:[email protected]:3306/test‘) #连接库,驱动是pymysql
Sess_maker=sessionmaker(engine) #登录库
session=Sess_maker()
person = session.query(Pers).filter(Pers.id==‘1‘).one() #查询数据
print(person.name)
# person=Pers(id=‘3‘,name=‘Nina3‘)
# session=Sess_maker()
# session.add(person) #插入数据
# session.commit()
# session.close()
88、WEB开发。
1)WEB服务器(HTTP服务器):与客户端打交道,处理前端静态内容(session、request、response、HTML、js、CSS等),如Apache、Nginx、IIS。只有Apache是纯web服务器!
2)应用服务器:为应用程序处理后台业务逻辑,客户端应用程序可以调用的方法,生成动态内容,如 Weblogic(Java)、WebSphere(IBM)。
然而,现在大多数应用服务器也包含了Web服务器的功能,如Tomcat、IIS、WSGI。
1、HTTP请求方法:GET与POST,GET仅请求资源,POST会附带用户数据(区别于HTML表单的get、post方法)。一个HTTP请求只处理一个资源。
响应代码:200表示成功,3xx表示重定向,4xx表示客户端发送的请求有错误,5xx表示服务器端处理时发生了错误。
web服务器工作:接受HTTP请求、解析HTTP请求、发送HTTP响应。
HTTP GET请求的格式,每个Header一行一个,换行符是“ \r\n ”:
GET /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3
HTTP POST请求的格式,包含body通过“ \r\n\r\n ”来分隔:
POST /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3
body data goes here...
2、web过程:
a.浏览器发送一个HTTP请求;
b.服务器收到请求,生成一个HTML文档;
c.服务器把HTML文档作为HTTP响应的Body发送给浏览器;
d.浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
3、HTML定义了页面的内容,CSS来控制页面元素的样式,而JavaScript负责页面的交互逻辑。
4、WSGI服务器:Python定义的Web服务器和应用服务器之间的一种通用接口。例:
def app(request,response): # web app用来处理请求和响应。request处理请求信息;response处理响应信息。
response(‘200 OK‘,[(‘Content-Type‘,‘text/html‘)])
body=‘<h1>Hello,world!%s</h1>‘ %(request[‘PATH_INFO‘][1:])
return [body.encode()] #返回列表类型
httpd=make_server(‘localhost‘,2017,app)
httpd.serve_forever()
89、web服务框架:很多框架都自带了WSGI,比如 Flask,webpy,Django、CherryPy等。
flask:需pip install flask,例:
app=Flask(__name__)
#获取首页
@app.route(‘/‘,methods=[‘GET‘])
def home():
return ‘<h1>HOME</h1>‘
90、MVC模式:M(模型) ——业务数据(或业务逻辑),这是应用程序的主体;
V(视图) ——用户交互界面(模板);
C(控制器)——接收来自界面的请求,处理用户界面数据显示。
91、异步IO(协程(coroutine)):一个主线程,子程序中断,可以同时处理多个IO请求,并且没有切换线程的操作,效率高。
能取代多线程和多进程。如读写磁盘文件、网络数据的异步问题。
多线程和多进程的模型虽然解决了异步问题,但是系统不能无上限地增加线程,系统切换线程的开销也很大。
sync:同步;
async:异步。
92、异步IO库:asyncio,编程模型是一个消息循环,从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行。
1)asyncio提供了完善的异步IO支持; #Python3.4开始
2)异步操作需要在coroutine(如函数)中通过yield from完成;
3)多个coroutine(如函数)可以封装成一组Task然后并发执行。
例:
import asyncio
import threading
@asyncio.coroutine
def hellopf():
print(‘Hello!!‘,threading.current_thread())
yield from asyncio.sleep(2)
print(‘World!!‘,threading.current_thread())
task=[hellopf(),hellopf()]
loop=asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(task))
loop.close()
# Python3.5变化:
a.把@asyncio.coroutine替换为async;
b.把yield from替换为await。
(日后继续更新...)