Python 小知识
简单知识
-
Python 导入模块的两种方法:
- 直接import package as 变量名
- from 包名/包名.类名 import class.name/ func.name
-
对字符串的操作
1. 不换行打印 print("set",end=" ")---->set ' ' 2. a.replace('原字符','替换字符') 显示的是测试的结果对原字符串没有影响 a= a.replace('原字符','替换字符')这就是更改了原字符串的操作 3. str = "-"; seq = ("a", "b", "c"); # 字符串序列 print str.join( seq ); ---->a-b-c 4.slice(start, stop[, step])切片 字符串[ : : -1] 反向输出 5.split(分割)默认以空白字符(空格、换行、制表符来分割) 6.成员操作符 in / not in 7.a=" " a.startwith()指定开头 / a.endwith()指定结尾 8.a.find(' ') 第一次出现指定字符串的位置,从左到右 9.a.rfind(' ') 第一次出现指定字符串的位置,从右到左 10.a.count(' ') 指定字符出现的次数 11.a.strip(' ') 去除首尾的信息,默认为空格 a.lstrip(' ') /a.rstrip(' ') 单个左右 12.a.capitalize() 一行字符就第一个字母大写 13.a.title() 每个单词都首字母大写 14.a.upper() 全部单词大写 a.lower() 全部单词小写 15.a.swapcase() 产生新的字符串,大小写与原来的字符串全部相反。
-
格式排版:
a="set" print(a.center(10,"*")) ***set**** ****************************************** a="set" print(a.ljust(10,"*")) set******* ****************************************** a="set" print(a.rjust(10,"*")) *******set
-
格式化输出:
a="名字是{0},年龄是{1},{0}是个好小伙".format("HYJ",18) print(a) 名字是HYJ,年龄是18,HYJ是个好小伙 (对其与填充)
-
可变字符串 io.StringIo() Python字符串属于不可变对象,不支持原地修改
修改字符串可以使用io.StringIo()对象或者array数组a="hello hit" import io sio =io.StringIO(a) print(sio.getvalue()) #将结果显示出来 sio.seek(6) #将光标移至6的位置 sio.write("s") print(sio.getvalue()) ****************************** hello hit hello shit
-
数值类型和字符串类型的相加、相乘、相连
3+2=5 / "3"+"2"="32" / (2,3)+(4,5)=(2,3,4,5) / [2,3]+[4,5]=[2,3,4,5] 2*3=6 /"set"*3="setsetset" / (2,3)*3=(2,3,2,3,2,3) / [2,3]*3=[2,3,2,3,2,3] a=3 a<<2 a=12 ---->2^2*3=12
-
-
divmod---->divmod(a,b)----->a % b = c…d 最终形式是以(c ,d )展现
-
round ------>浮点型数值四舍五入
-
代码
if __name__='__main__'
- 直接作脚本运行
- import到其他python脚本中使用
- 每个Python模块中都有内置函数
'__name__'
,当模块运行时名为'__main__'
. - Python 文件可以以
if __name__='__main__'
为入口,意味着当其他类调用这个包含if
的文件时,if以下的内容函数体不会被调用,解决被导入时被动执行问题。
-
什么是模块的搜索路径?
- 模块的加载顺序
- 搜索内中已加载的模块
- 搜索Python内置模块
- 搜索sys.path
import sys sys.path #获取路径列表 sys.path.append(dir) #添加搜索路径
from 包 import * 每个Python包被建立的时候会自动建立一个 __init__文件,要是想改变*中所加载的模块 内容则要改写__init__文件,里面写__all__函数 __all__('变量','model,fucation','Python 模块')
- 模块的加载顺序
Python常用序列结构
列表、元组、字典、集合
列表:
-
增加元素
list.append(x) 将一个元素添加至尾部
list.extend(alist) 将一组元素增加至尾部
list.insert(index,X) 在指定的位置上增加X -
删除元素
list.remove(x) 在列表中删除首次出现的X元素
list.pop([index])默认为删除最后一个,也可以删除指定位置元素
list.clear() 删除列表所有元素 -
三种列表排序方法
1.正序排列 a.sort()
2.逆序排列 a.sort(reverse=True) True从大到小 / False从小到大
3.乱序排序 import random
random.shuffle(a)
4.建立新的列表排序 内置函数 sorted(a) 正序的
5.内置函数reversed() 对列表反向生成一个迭代器,通过迭代输出,原列表不受影响
6.其他的内置函数:max、min、Sum、len (对于数值型列表) -
二维列表 ---->列表里面放列表
a=[
[ ],
[ ],
]
a=(1,2,3)
b=(4,5,6)
c=zip(a,b) ------>[(1,4),(2,5),(3,6)]
元组(不可变序列)
- 三种数据定义方式:a=(1,2,3) / a=1,2,3 / a=Tuple()
- 当元组的个数只有一个的时候,必须在后面加个’,’
- a.next() 元组内部的方法,每次输出一个。元组的访问/处理比列表快。
字典
-
字典的定义方式有三种:
{'key1':value1,'key2':value2}、 dict(key='value',key2='value2')、 dict([("key1","value1"),("key2",value2)])
-
有dict关键字后面跟元组(),没有的话就要跟{ };
-
key 、value、items 其中key是任意不可变数据,且不可重复.
-
A是一个字典,可以通过键名去获得键值 A.get(‘key1’,‘键名不存在’) ---->value1,如
果key1不存在,则输出"键名不存在". -
A.items(键值对)、A.keys(所有键名)、A.values(所有键值).
-
可以通过Zip来创建字典对象 A是键名 ,B是键值 C=dict(zip(A,B))即创建字典.
-
可以通过fromkeys来创建空字典
a=dict.fromkeys([“name”,“age”,“job”]) a[“键名”]=键值 没有就增加,有就覆盖. -
A、B是两个字典。 A.update(B) 将B中的键值对全部添加到A中,键名重复就值覆盖.
-
删除键值对用 del(A[‘键名’]) 删除所有键值对 clear().
-
b=A.pop(‘age’) b---->等于被删除键名的值.
-
popitem() 随机删除和返回被删除的键值对
-
序列解包 :
1. x,y,z=(10,20,30) / a,b,c=[10,20,30] -----> x,y,z/a,b,c=10,20,30 2. 序列解包用于字典: S={’name‘:'HYJ',"age":18,"job":"student"} name,age,job=S.values() 字典的核心内容是散列表(总是有空白元素的数组,每个单元叫bucket(为键/值引用对象)) 本质上所有的数据都可以用表格来表示,通过列表方式.get去利用键名曲获得值。 键必须是可散列:1.数字、元组、字符串都是可散列的 2.支持hash() ----->用bin(hash( ))转为二进制 3.能通过__eq__()方法检测相等 4.a==b 则hash(a)==hash(b)
集合
- 概念:集合是无序的,元素不可重复,是底层字典的实现,使用字典符号{ }.
- 可以使用set方法将列表、元组等可迭代对象转换为集合.
- remove()删除指定元素、clear()清空整个集合.
- 对集合的并、交、差集
并集 a | b a.union(b) 交集 a & b a.intersection(b) 差集 a - b a.difference(b)
海龟绘图
- 绘图的基本抬笔、落笔
import turtle x=turtle.pen() turtle.penup() turtle.forword / circle() turtle.pendown()
- 海归绘图Turtle在最后加turtle.done() ---->不在最后完成时关闭画布
- 调整画笔的速度 t.speed(0/1) 0最快/1最慢 画笔的宽度为t.width()
碎片知识
-
如 id = 3 栈就是一个变量的内存空间,一个地址(id),堆就是变量对象(id,type=int,value=3)
-
计算机中的时间是从1970/1/1 00:00:00开始的
-
‘is’ / ‘==’ 的区别 is是判断两个变量引用对象是否是同一个,==是对象的值是否相等
is是对象的地址,==默认调用对象的equal()方法 -
整数缓存问题 对较小的整数进行缓存
(用python自带的IDLE去做,较小整数的范围是[-5,256],保存文件为[-5,任意整数])a=3 id=1812902176 a=1000 b=3 id=1812902176 b=1000 print(a==b) --->True print(a==b) --->True print(a is b )--->True print(a is b )--->False
-
内置函数ord( ),将字符转变为16进制,ord(‘A’)=65,Python3直接使用Unicode
-
内置函数char( ),将十进制码转换为字符
-
内置函数bin( )将十进制数转换为二进制数
-
字符串中有单引号则外面要用双引号进行包围,如果字符串里面是双引号则外面要用单引号包围,多行内容可以用三引号进行包围。
-
条件表达式:条件为False情况下
False 、 0 、0.0 、空值None 、空序列对象(空列表、元组、集合、字典字符串)
-
三元条件运算符 (条件为真的值 if (条件表达式) else (条件为假的值))
-
代码的优化 :1.嵌套循环,尽量减少内循环的计算
2.局部变量查询较快
3.链接字符串用join( )而不用+
4.列表进行插入和删除的操作尽量在尾部进行
推导式
- 列表推导式:
x=[语句 for i in 条件 [if 判断](可省略)]
- 字典推导式:
x={c:text.count(c) for c in text [if 判断](可省略)}
(统计每个字符的个数) - 集合推导式:
x={语句 for ____条件 [if 判断] }
- 生成器推导式 用小括号
a=(x for ____ [ if 判断 ])
最后用print(tuple(a))显示,元组没推导式
函数 (def)
-
函数有内置函数、标准函数库(import导入)、第三方库函数、自定义库(def)
-
函数也是对象------>堆里面有一个内存块,函数必须要有返回值return,结束函数运行
-
形参和实参:形参是定义函数时的参数/实参是调用函数时传递的参数
-
函数也是对象,可以作为参数来传递,也可以作为返回值来返回
def test01(): print("It's ok!") t=test01 t() #将test01的id复制给t,这时候t()和test01()是指向同一个堆的。
-
变量的作用域(全局变量 / 局部变量)
全局变量:全局变量是可以被本程序所有对象或函数引用。
局部变量:在函数值中(包含形参)声明的变量
局部变量的引用比全局变量快、 全/局变量同名,则函数内隐藏全局变量使用同名局部变量 -
在自定义函数是要改变全局变量的值时,增加global进行声明
-
stack frame栈帧---->调用函数时,创建一个栈帧,里面存放局部变量。调用完成时,栈帧删除。
-
传递可变对象是对实参的同一对象进行操作,会改变原变量值。
-
可变对象有字典、列表、集合、自定义对象。不可变的有:数字、字符串、元组、int、float、fucation、布尔值
-
参数类型:位置参数、命令参数、默认值参数、可变参数(*args、**kwargs)
def fucation1(a,b,*args): print(a,b,arg) def fucation2(a,b,**kwargs): print(a,b,kwargs) *args:将多个参数搜集到一个元组中,arg可以是一个参数,也可以是多个参数。 **kwargs:将多个参数收集到一个字典中。 可变参数的前面有值会一一对应,最后为可变参数。
-
强制命名参数
def fucation3(*args,a,b): print(args,a,b) fucation3(1,2,3)----->报错 因为元组可以为多个,'1,2,3'会被认为是一个元组的值,少a,b值。 应该赋值改为 fucation3(1,a=2,b=3),最终的结果为'(1),2,3'.
-
Lambda表达式(用来声明匿名函数)
add = lambda x, y : x+y add(1,2) # 结果为3
- lambda表达式结构:a=[lambda arg1,arg2,arg3 :表达体(函数体)]
- 当有多个lambda表达式中,表达体变成列表格式,中间用’,'隔开。
- print([数组下标][参数的value值])
-
eval函数 ----->将字符串str当成有效表达式来求值并返回
x=7 参数global必须是字典/参数locals任意映像对象 eval('3*x') eval(source,[global,[locals]]) source是一个python表达式,当后面没有内容 *************** 当source后面跟着字典对象,则前面的source的成员时后面的字典成员。 21
-
递归
def fucation(n)" if n=1: ruturn 1 else: return n*fucation(n-1) ret=fucation(5)------->1*2*3*4*5=120
-
嵌套函数(函数里面有函数)
def a (): print("It's first") def b(): print("It's secod") b() a() 函数b服务于函数a,不能从外部去调用b() 当内置函数要去修改外面的成员值时必须声明nonlocal 声明外部函数的局部变量内置函数的全局变量修改global
-
def printname(ischinese,name,familyname): def format_print(a,b): print("{0},{1}“.format(a,b) if ischinese: format_print(familyname,name) else: format_print(name,familyname) 设计这个函数的意图是区分中国人、外国人的姓名组合。这里其实最关键的是ischinese这个形参 这里让你输入的其实是True/False,用来判断该怎么组合,然后调用函数。
拷贝(copy)
-
拷贝分为(浅拷贝和深拷贝)
-
浅拷贝(copy):不复制内容,只复制子对象的引用,传递不可变对象。
-
深拷贝(deepcopy):复制子对象内容和对象内存,子对象要修改不影响原内容。
浅拷贝:如果复制列能够找到原对象地址则改变原对象内容,否则即改变复制内容。 import copy a=[10,20,[5,6]] b=copy.copy(a) print(b) b.append(30) b[2].append(7) print(a) print(b) ******************* [10, 20, [5, 6]] [10, 20, [5, 6, 7]] [10, 20, [5, 6, 7], 30]
深拷贝:不可变对象的可变子成员是可变的则方法内修改了这个可变对象原对象也会发生改变。 import copy a=[10,20,[5,6]] b=copy.copy(a) print(b) b.append(30) b[2].append(7) print(a) print(b) ******************* [10, 20, [5, 6]] [10, 20, [5, 6, ]] [10, 20, [5, 6, 7], 30]
-
类(class)
-
定义类 Class class_name([可以选择继承,也可以忽略]):
-
每个类都有构造方法
'__init__'
,比如:Class Student: def __init__(self,name,age) self.name=name self.age=age def introducemyself(self): print("大家好,我是{0}".format(self.name))
-
在
__init__
初始化的时候进行self成员的创建,以后的方法参数加上self都可以去调用self成员。 -
在类中,其他的函数如果加上了self参数,就变成了方法。
-
调用的过程结束是不含返回值的,需要自己定义输出,通过
类名()
来调用构造函数。 -
调用方法的两种方式:
对象1=类名("__",__) 对象2=类名("__",__) 对象1.方法名() 类名.方法(对象2)
-
isinstance(对象,类名)------>判断一个对象是否是属于这个类的。
类里面的对象,通过类名.成员调用 / 实例对象通过`__init__(self,__,__)`调用
-
类方法:通过装饰器@classmethod 在定义函数时对象用cls去调用类对象
-
静态方法:@staticmethod 通过类名.方法(赋值)去调用
-
在定义方法前面写上 析构函数(垃圾回收机制)
'__del__
’ -
Python 中是没有方法重载的,方法重名后是按最后一个方法进行传参的,当在类外面定义函数时想用对象进行调用即 类名.对象名=外部定义的函数名; 给参数赋一个默认值是一个好方式。
-
私有成员
class a(object): def __init__(self,name,age): self.name=name self.__age=age #在成员变量前面加上'__'就是将成员变成私有的方式 def __work(self): #在方法前面加'__'将方法变成私有方法 print(self.__age) e=a("HYJ",18) e.name------------>'HYJ' e._a__work() ---->18 调用内置对象私有方法 / 对象:通过对象名._类名.__成员名(对象 / 方法)
class a: def __init__(self,name,age): self.name=name self.__age=age #在成员变量前面加上'__'就是将成员变成私有的方式 self.__company = "123" def __work(self): #在方法前面加'__'将方法变成私有方法 print(self.__age) e=a("HYJ",18) print(e._a__company) -------> '123'
-
当类中有私有成员时,建立与查询私有成员用 get()、set() 进行查询和建立。
-
用@property修饰函数的时候,可以直接用对象名.函数调用方法,不需要加()。
-
继承
-
Python 与其他语言最大的不同是可以进行多继承的。一个子类可以继承多个父类
-
要说继承,先要说一下构造函数。Java要求是与类名相同并且无返回值,而Python则是强制要求命名为
__init__()
。 -
当创建类的对象时,会自动先调用构造函数,一般用于初始化。构造函数可以不写,那么程序会隐式自动增加一个空的构造函数。
-
如果类定义中没有指明继承对象,则是默认继承Object类。
class 类名(父类1,父类2):
class Person: def __init__(self,name,age): self.name=name self.age=age def say_age(self): print("我的年龄是{0}".format(self.age)) class Student(Person): def __init__(self,name,age,score): #这里面的参数会对照父类的参数进行赋值。 Person.__init__(self,name,age) #必须显示是父类初始化方法,不然解释器不会去调用。 self.score=score S=Student("HYJ",18,100) S.say_age() ------>'我的年龄是18' print(S.name)----->'HYJ' print(S.score)---->18
-
子类会继承父类的所有公共方法。
-
查看类的继承结构 利用
类名.mro()
来查看、class A: pass class B(A): pass class C(B): pass print(C.mro()) C----->B----->A----->Object
-
子类继承父类,用Super去调用父类成员,方法。
-
利用类名去直接调用类里面的方法----->类名.方法名()
-
-
多态
- 多态的两个知识点:1.多态是方法的多态
2.多态的条件:继承 和 重写(多个子类去继承同一父类实现多态) - 可以用
if isinstance(继承父类的多态子类,唯一父类)
来判断实例是否属于哪一个类。 - 多态说的简单一点就是一个父类的某个方法pass,子类去继承重写这个父类的方法。
-
import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): #动物的形态之一:人 def talk(self): print('say hello') class Dog(Animal): #动物的形态之二:狗 def talk(self): print('say wangwang') class Pig(Animal): #动物的形态之三:猪 def talk(self): print('say aoao')
- 多态的两个知识点:1.多态是方法的多态
文件操作
-
F = open("文件名",'打开模式') F.close()
- 这个就是最基本的文本打开操作,最主要的是不要忘记变量F的关闭。
- 访问的模式:
- r.以读的方式打开文件(默认)
- w.打开一个文件只用写入的方式。文件要是存在了就覆盖,不存在就创建文件。
- a.用于文件内容的追加。如果文件存在就追加,不存在就创建文件写入。
- r+ / w+ / a+/ 打开一个文件用于读写
- 如果使用多次读的方式打开文件,那么后面读取的数据是上次读完的位置开始的。
-
F = open("文件名",'打开模式') F,write(' ') ----->(如果文件存在则将文件内容清空再写入) F.read(5) -------->(读取文件5个字符) F.close()
- read / write 都是单字符一个一个操作的 readlines是以行作为单位进行操作的
- print(("%d,%s")%(数字,字符串))
- 实现文件的复制:
- 利用input将原文件名写入(包括后缀名)
- 将文件变成可读文件,用r的方式打开
- 做判断,判断文件是否打开
- 提取文件的后缀名
- 组织新名字
- 创建新的文件
- 将旧文件一条一条复制到新文件中
- 旧文件关闭
- 新文件关闭
OOP(Object Orient Project)
-
编写类时后面跟().本质上是没有去别的,加()的作用是为了继承类。
class A <->class A()
-
class A() <---->class A(Object)
这两个是一样的,因为默认继承的就是Object. -
私有成员访问问题(__私有成员变量名)(当前类或者对象使用)
-
Python的私有并不是真正的私有,是一种name mangline的改名策略,可以利用
实例对象._类名.__私有成员
进行访问(可以修改它的值),利用类名.__dict__
返回一个带成员名和值的字典。 -
受保护的封装(protected):受保护的封装,将可以在类或子类中都可以访问,但是外部不行。在成员名称前添加一个
'_'
进行封装。 -
子类继承父类调用父类成员问题:
- 子类继承父类是用子类访问父类成员提高代码复用.
- 可以利用
super().父类成员
进行父类成员的调用.
-
继承的特性
- 所有类都是继承object类,即所有类是object类的子类.
- 子类继承父类除私有成员以外的一切内容.
-
构造函数----->在类进行实例化之前进行调用
Class A(): def __iniit__(self): #每次实例化前第一个被调用 print("Hello World") A() ---->'Hello World' #实例化的时候括号里面参数应与构造函数一致。
-
A()
对于直接调用的实例化来说,第一个调用的函数是'__call__'
-
对于
a=A()
对象实例化来说,第一个被调用的函数是'__new__'
,第二个是__init__
-
子类继承父类,首先查找自己类中的构造函数.如果没有的话就去调用父类的构造函数.
-
Python的单继承 / 多继承
-
继承多类时,构造函数应与继承的类相一致,然后后面所跟的函数加self.
-
菱形继承
class A(): pass class B(A): pass class C(A): pass class D(B,C): pass
-
多继承
class A(): pass class B(): pass class C(): pass 1 2 3 #继承顺序,查找成员/方法的父类顺序 class D(C,B,A): · pass
-
-
子类继承父类后调用父类的继承函数
父类名.__init__(self,形参)
super(子类名,self).__init__(self)
Python 3 中super() <—>super(子类名,self)
-
例子 子类继承父类的构造函数需要添加函数功能
class A(): def __init__(self): #定义类里面没调用自己类方法的办法 print('A') # self.函数名(形参) class B(A): def __init__(self,name): print('B') print(name) class C(B): def __init__(self,name): 1、2 继续添加函数功能
-
issubclass(子类,父类)用来判断A是否是B的子类。
-
hasatter 用来检测成员是否在对象里面
-
类成员的三种相关的属性操作:
- get获得属性
- set修改、创建属性
- delete 删除属性
-
属性函数property(类成员描述符)
- 类成员名=property(fget,fset,fdel,doc)
class A(): def fget(self): return def fset(self,形参): pass name=property(fget,fset,doc) a=A() a,name #不传入参数指利用name返回fget函数里面的内容 a.name(实参) #将实参传给形参调用fset函数的内容
- 类成员名=property(fget,fset,fdel,doc)
-
类名.dict --->方法 / 类名.doc--->说明 / 类名.name--->类名 / 类名.bases--->顺序父类
魔术方法
- 前后被双下划线包围的方法
- 函数里面最基本的魔术方法就是
'__init__(self,形参)'
def __new__(cls,type)
继承的是不可变类型如tuple、str等类型用new- 需要注意的是类型对象的无限递归问题,要用
return str.__new__(cls,tuple)
方法 - 当
'__init__(self,形参)'
/'__new__(cls,tuple)'
同时出现时最先调用'__new__(cls,tuple)'
然后开始创建的时候初始化函数用来传递值。 def __call__(self, *args, **kwargs):
class A(): def __init__(self): print('A') def __call__(self, *args, **kwargs): #当类被实例化时的时候,首先调用的是__init__函数 当实例对象被当做函数调用时a(),则调用__call__(self, *args, **kwargs) print('B') a=A() 'A' a() 'B'
class A(): def __init__(self,name): self.name=name def __gt__(self,obj): print("{0}会比{1}大吗?".format(self,obj)) return self.name>obj.name #当没有返回值的时候,结果为None stu1=A('one') stu2=A('two') print(stu1>stu2) ************************************ <__main__.A object at 0x0000020CE1A6B978>会比<__main__.A object at 0x0000020CE1A6B780>大吗? False
- 这是实例与实例之间的比较.
stu1=A('one')
/stu2=A('two')
- 用于比较的魔术方法
__cmp__(self,other)
实现了所有符号(<,==,!=,etc)- self < other 返回负数
- self = other 返回0
- self > other 返回正数
__eq__(self,other)
=__ne__(self,other)
!=__It__(self,other)
<__gt__(self,other)
>=
抽象类(abstract)
-
不实现函数内容
-
利用abc模块申明一个类
-
抽象方法不允许实例化,只能继承使用。继承的子类必须实现所有抽象方法
import abc class A(metaclass= abc.ABCMeta): 定义抽象方法:@abc.abstractmethod 定义类抽象方法:@abc.abstractclassmethod 定义静态方法:@abc.abstractstaticmethod
自定义类(组合类)
- 外部定义一个类、外部编写一个函数,通过组合拼接在一起。
class A(): pass def B(): print('A') A.B=B #创建类中的函数B,将外部的函数B方法复制到类中的函数B a=A() a.B() ---->'A'
利用实例对象添加函数B from types import MethodType class A(): pass def B(self): print('A') a=A() a.B=MethodType(B,A) a.B() ---- >'A'
利用Type函数造类 def A(self): pass def B(self): pass Type格式:Type(name,bases,dict) name是类名,dict是类型 A=Type('A',(Object,)dict(A=A,B=B)) a=A() a.A() a.B()
- 元类的写法
class AMetaclass(type): #继承type def __new__(cls,name,bases,attrs): 业务代码 (注意无限递归) return type.__new__(cls,name,bases,attrs) class B(object,metaclass=AMetaclass): pass
Error(异常类)
-
指的是在语法逻辑正确的前提下出现的问题
try: 函数体 except(Exception1,Exception2): else: finally:
-
执行的过程为
- 执行try下面的语句
- 出现异常查找except中的异常
- 不管有无异常都执行finally语句
-
在异常中,except ,else和finally可以选择使用。
-
对于except中的异常类存放顺序是越清楚的子类放前面,越大的父类放越后面,异常基类Exception
-
获得异常后
except 异常类 as e:
在这里e就是一个实例,通过print (e)
显示异常信息。 -
raise关键字可以手动引发异常,raise后面跟异常类。然后不往下执行去寻找异常类
-
自定义异常类
class 类名(继承的异常类):
当系统找不到自己所定义的异常类时,就回去寻找被继承的父类。这就是所谓的系统向上查找。 -
只要是raise手动抛出异常就用自定义类,自定义类包含异常代码问题提示,问题发生行,方便快速定位现场
常用的系统模块(calendar、time等)
- 常用的模块有calendar(日历)、time、datetime、timeit、os、shutil、zip、math、string
- 在使用模块前我们都应该先用import导入模块,string是特例。
- calendar模块
cal=calendar.Calendar(2019,W,L,C)
- W=每个日期之间的间隔字符数
- L=每周所占的行数
- C=每个月之间间隔字符数
calendar.sleap(年份) return boolean 判断是否是闰年
calendar.leapdays([a,b)) 获取区间内的闰年的个数
calendar.momth(年,月) 打印某年某月的日历字符串
a,b=calendar,momthrange(年,月)返回一个数组a是周几是开始天b是一个月几天
calendar.momthcalendar(年,月) 返回一个月每天的矩阵,没有天数用0表示
calendar.prcal(年份) 直接打印某年的日历
calendar.weekday(年,月,日) 返回的数据是显示周几
time 模块 时间从1970年1月1号0时0分0秒至今
UTC时间-->世界标准时间 中国时间 UTC+8
夏令时 -->将夏天的时间调快一个小时
时间元组 -->一个包含时间的普通元组
import time
例:
time.timezone 当前时区和UTC时区相差的秒数,在没有夏令时的情况下的间隔
time.altzone 获取当时时区的秒数,在夏令时的情况下
time.daylight 检测当前是否是夏令时状态
time.time() 获得一个时间戳
time.localtime() 得到当时时间的具体架构
当前时间的时间架构 包含9项
0 年 tm_year
1 月 time_month
2 日 time_mday
3 时 time_hour
4 分 time_min
5 秒 time_sec
6 第几周 tm_wday
7 第几天 tm_yday
8 夏令时 tm_isdst (-1,0,1)
t=time.ctime() print(t) #获得字符串化的当前时间
获得cpu时间 clock3.0~3.3版本使用
sleep 使程序进入睡眠时间 time.sleep(1) 休眠一秒
datetime 模块
例:
dt=datetime.date(年,月,日)
print(dt.year/dt.momth/dt.day)
from datetime import datetime
dt=datetime(年,月,日) #datetime中常用的类方法有today、now、utcnow、fromtimestamp
print(dt.fromtimestamp(time.time())) #从时间戳中返回本地时间
sleep测试:
def p(n):
time.sleep(n)
t1=time.time()
p(1)
t2=time.time()
print(t2-t1)
利用timeit时间工具测量时间间隔
例:
t=timeit.timeit(stmt="",setup="",number="") #stmt是执行体可以是表达式、说明文本、函数 \setup是环境变量 形参 \ number是执行次数
t1=timeit.timeit(stmt="[i for i in range(1000)]",number=10000)
c="""
sum=[]
for i in range(10000):
sum.append(i)
"""
t2=timeit.timeit(stmt=c,number=10000)
import timeit
s="""
def doit(num):
for i in range (num):
print(i)
"""
t=timeit.timeit(stmt="doit(num)",setup=s+"num=3",number=10000)
#最终的结果为所消耗的时间和潺摄哥的循环(setup中的形参很重要)
OS模块
例:
os.path 系统路径的相关操作 路径分为绝对操作和相对操作 /绝对操作从根目录开始,相对操作从当前工作环境开始
os.getcwd() 获得当前工作路径
os.chdir(路径) 更改当前工作环境目录
os.listdir(路径) 获得一个目录的子目录和文件列表
os.makedir(递归路径) 递归创建文件夹 / 在工作目录下创建
rst=os.system(系统命令)
print(rst) 返回值:打开一个shell或者终端界面
rst=os.getenv("环境变量名") 获得指定系统的环境变量
os.curdir 当前目录 .
os.pardir 父目录 ..
os.sep 当前系统路径分隔符 windows:"\" linux:"/"
os.linesep 当前系统的换行符 "\r\n"
os.name 当前系统的名称
OS.path模块 (必须先导入os.path)
例:
import os.path as pa
absp=pa.abspath("路径") #将当前路径转化为绝对路径
利用os.path.join(path,paths*) 将路径进行拼接
利用spilt去分割文件和文件夹
isdir 用来判断是否是一个目录 exits()检测文件目录是否存在
shutil 模块(主要是用于文件的拷贝)
例:
import shutil
rst=shutil.copy(来源路径,目标路径)
print(rst)----->返回的结果是目标路径
copy <---->copy2的区别:尽量保留元数据(权限)
copyfile--->shutil.copyfile(源地址,目标地址)
move--->shutil.move(源,目) 权限问题,不能移动至Adminstrator
归档和压缩的概念:归档->将多个文件或者文件夹合并到一个文档中 压缩->用算法将多个文件或者文件夹有损或者无损的合并到一个文件中
shutil.make_archive("归档后的目录和文件名","后缀","需要归档的文件夹")
shutil.unpack_archive("归档文件地址","解包地址")
Zip模块
例:
import zipfile
zf=zipfile.Zipfile('文件的绝对路径')
rst=zf.getinfo("文件名") #获取zip文档内指定文件内容
name=zf.namelist() 获取zip文档内所有文件名称
jieya=zf.extractally('绝对路径') 解压缩
Random模块
random.random() 随机生成一个0~1的随机数
例:
L=[str(i)+"haha" for i in range(10)]
rst=random.choice(L)
print(rst) 随机输出列表中的某个值
L=[for i in range(10)]
print(L)
random.shuffle(L) 打乱顺序输出
print(L) 对原列表进行打乱输出
random.randint(a,b) 返回一个[a,b]的随机整数
函数式编程1
a=Lambda x:表达式 系统高阶函数-map 具有映射功能的函数
reduce 归并需要从functools包中导入
from functools import reduce
reduce([1,2,3,4,5])=f((f(f(1,2),3),4),5)
例:
def A(x,y):
return x+y
rst=reduce(A,[1,2,3,4,5])
print(rst) ---->1+2+3+4+5=21
函数式编程2
filter函数-->符合条件的数据合成一个新的列表 return boolean
filter(f,data) f是需要条件 / data是原数据
高阶函数排序sorted(对象,reverse=boolean,key=字典键名) 对象可以是列表或者元组
返回函数:当一个函数在内部定义函并且内用外部参数或者局部变量,当内部函数被当作返回值的时候,相关参数和变量保存在返回的函数中。(闭包)
例:
def myF4(*args):
def myF5():
rst=0
for i in args:
rst+=i
return rst
return myF5
返回闭包时,返回函数不能引用任何循环变量
例:
def count():
fs=[]
for i in range(1,4):
def f():
return i*i
fs.append(f())
return fs
f1,f2,f3=count()
print(f1)
print(f2)
print(f3)
# f1=1,f2=4,f3=9
def count2():
def f(j):
def g():
return j*j
return g()
fs=[]
for i in range(1,4):
fs.append(f(i))
return fs
f1,f2,f3=count2()
print(f1)
print(f2)
print(f3)
# f1=1,f2=4,f3=9
装饰器
- 装饰器:原有代码的基础上新增功能,使用@语法,每次要扩展函数定义前使用@+函数名
例:
def w1(func):
def inner():
print("正在验证----")
func()
return inner()
@w1
def f1():
print("f1----")
@w1
def f2():
print("f2----")
第一种方法 +@
f1()
f2()
第二种方法 手动执行 实例化 将扩展的功能加上
f1=w1(f1)
f1() 把发传递给func func指向了f1原来的那个函数,w1返回inner这个函数的引用,f1指向了这个引用
f1指向了inner这个函数的地址 f1()现在调用的就是inner这个函数
进制转化 int("12345",base=8) str--->int 转化为八进制
例:
def int16(x,base=16):
return int(x,base) 先定义函数,在实例化使用
偏函数 functools.partial
例:
from functools import partial as pa
int16=pa(int,base=16)
int16("12345")--->"74565"
Zip函数 -->组合成为一个新的tuple列表
例:
L1=[1,2,3] L2=[4,5,6] L3=zip(L1,l2) l3=([1,4],[2,5],[3,6])
enumerate 函数 -->对可迭代对象的每一个元素都配一个下标
例:
L1=[1,2,4,6,8]
em=enumerate(L1,start=0) #意味着第一个元素的下标为0
collection 模块 -->可命名tuple
例:
from collection import namedtuple
import collection
point=collection.namedtuple("point",[x,y])
p=point(11,22) #point实例化 可以利用namedtuple去计算一些圆形的面积
p.x=11
p[0]=11
deque 方便解决频繁删除插入带来的效率问题
例:
from collection import deque
q=deque(['a','b','c'])
q.append('d')--->q=(['a','b','c','d'])
q.appendleft('x')--->q=(['x','a','b','c','d'])
defaultdict 当字典对象键名不存在时系统给的默认值
例:
from collection import defaultdict
func=lambda : "123"
d2=defaultdict(func) #假定如果没有key键的话,则返回func
d2["one"]=1
print(d2["two"]) -->'123' 因为键值对中没有key -"two" 所以返回一个默认值
counter 统计字符的个数
例:
from collection import counter
c=counter('ab','ab','b')
print(c) --->{'ab':2,'b':1} 直接将所有的字符按照字符和个数进行组合显示
调试技术调试的流程为单元测试->集成测试->测试部测试\可分为静态测试和动态测试
在Pycharm中运行可以为run模式和debug模式。程序员在debug模式下遇到断点会暂停 setup into break point 设置断点
文件模块
with open(r"路径+文件.后缀",'mode') as f:
下面是对文件f进行操作,不需要close关闭
以行完整读取内容 strline=f.readline()行读
while strline:
print(strline)
strline=f.readline()
strchar=f.read() 从头取到尾,可规定读取字符个数
print(strchar)
读取指针 seek(offset,from) 开头 from是取值范围(以字节为单位) from =0 从文件头开始偏移 from=1 从文件当前位置进行偏移 from=2 从文件末尾开始偏移
read的单位为字符,即为一个汉字一个字符
tell函数,告诉你当前的seek下标在那个位置
文件操作
write(str)->只能是字符串
writelines(str)->可能是字符串,也可能是字符序列 可以直接写入行
持久化保存 pickle->保存结构化数据
序列化 pickle.dump 写入 pickle.load 读取
例:
import pickle
age=19
with open(r"test01.txt",'wb') as f:
pickle.dump(age,f)
import pickle
with open(r"test01.txt",'rb') as f:
age=pickle.load(f)
print(age)
shelve模块 类似于字典形式保存数据 key value
例:
import shelve模块
she=shelve.open(r"shv.db") be
she['one']= 1 其中'one' 就是key 1就是value
she.close()
shelve 读取 --->不支持多个应用并行写入
she=shelve.open(r"she.db") she=shelve.open(r"shv.db",flag=r) flag表明只读操作
try:
print(she['one'])
except Exception as e: # she=shelve.open(r"shv.db",writeback=True) 写回操作,在shelve中更改键值的操作时,关闭shelve连接时,内容是在内存中的,并没有写回shelve的键值对中,可以用writeback进行回写
print(e)
finally:
she.close()
多线程 and 多进程
进程的概念:程序的一个运行状态,每一个进程都有自己独立的运行环境
线程的概念:一个进程的独立运行片段,一个进程又多个线程组成
GTL 全局解释器锁
python2.0-->thread包 python3.0-->_thread包 python线程通用包:threading包
例:
import _thread as thread
thread.start_new_thread((函数),(函数形参))
def main():
程序片
if __name__="__main__":
main()
while true:
time.sleep(1)
threading的使用
function A 、function B
例:
实例 t1=threading.Thread(target=A,args=(函数形参))
t2=threading.Thread(target=B,-rgs=(函数形参))
t1.start()
t2.start()
线程的调用过程是随机的,是由cpu决定的 threading.activecount()子线程的运行数量
for i in threading.enumerate:
i.getname() 用以获得程名
线程共享变量-->当多个线程同时访问一个变量的时候
线程锁:lock实例化 lock=threading.lock()
def MyAdd():
global sum=0,loopsum=100000
for i in range(1,loopsum):
lock.acquire()-->上锁
sum=sum+1
lock.release()-->解锁
线程安全问题:线程不安全的变量类型-->list、set、dict
线程安全类型->queue 是一个存放变量的数据结构,特点是先进先出,内部元素排队
生产者(Producer)/消费者(Consumer)
例:
Class Producer(threading.Thread):
def sun(self):
global queue
count=0
while true:
if queue.qsize<1000:
for i in range(100):
count+=1
msg="生成产品"+str(count)
queue.put(msg)-->放在queue数据结构中
print(msg)
time.sleep(0.5)
Class Consumer(threading.Thread):
def run(self):
global queue
while true:
if queue.qsize>1000:
for i in range 3:
msg=self.name+'消费了'+queue.get()
print(msg)
time.sleep(0.5)
if __name__="__main__":
queue=queue.Queue()
for i in range(50):
queue.put("初始产品"+str(i))
for i in range(2):
p=Producer()
p.start()
for i in range (5):
c=Consumer()
c.start()
线程的代替方案:Subprocess 完全跳过线程使用进程
Multiprocessing:使用threadin接口派生使用子进程允许多核或多cpu派生进程
p=Multiprocessing.process(target= ,args= )
死锁问题-->semphore
允许一个资源最多由几个线程同时使用
semphore=threading.Semphore(3) 能够同时被三个进程所使用
例:
def functionC():
if semphore.acquire:
for i in range (5):
print(threading.currentThread().getname()+'getsemphore')
time.sleep(0.5)
semphore.release()
print(threading.currentThread.getname()+'releasesemphore')
for i in range 8:
t=threading.Thread(target=functionC)
t.start()
派生类 class clockprocess(int,run):
例:
def __init__(self,interval):
super().__init__()
self.interval=interval
def run(self):
while true:
print("This time is %s" %ctime())
sleep(self.interval)
if __name__="__main__":
p=clockprocess()
p.start()
while true:
print(sleep.....)
time.sleep(1)
在OS中查看pid ppid查看关系
例:
def info(title):
print(title)
print("model_name",__name__)
print("父进程",os.getppid())
print("本身进程",os.getpid())
def f(name):
info('main_line')
print('hello world')
if __name__="__main__":
info("main line")
p=process(target=f,args=("bob"))
p.start()
迭代器iterator 生成器iterable
迭代器可以直接作用于for循环 可以被next调用
生成器可以直接作用于for循环
可以通过内置函数将迭代对象变成迭代器
iterable--->iterator
S='I love you'
s_iter=Iter(s) s_iter就变成了迭代器
例:
isinstance案例
form collection import Iterable
L=[1,2,3,4,5]
print(isinstance(l,interable))--->True
print(isinstance(l,iterator)) --->False
生成器-->generator 用yield返回就是生成器
一边循环一边计算下一个元素的机制
1.每次循环都生成for循环需要的下一个元素
2.如果到达最后一个元素,将显示stopIteration异常
3.可以被next调用 L=[x*x for i in range (5)] -->class 'list' G=(x*x for i in range(5))--> class 'generator'
例:
def test():
print('A')
yield 1 利用yield去代替return
print('B')
yield 2
print('C')
yield 3
t=test()-->生成生成器
A=next(t) -->'A'
B=next(t) -->'B' 将会是分段输出
例:
def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n+=1
return 'Done'
g=fib(5) 生成器生成
for i in range(5): 根据循环次数Iterator在最后一个时会弹出stopIteration异常
rst=next(i)
print(rst)
for i in g: 生成器最典型的用处就是在for循环中使用
print(i)
例:
def s():
print('-->start')
x=yield
print('-->recived',x)
sc=s()
print('111')
next(sc) -->预激/执行协程
print('222')
sc.send('zhexiao')
例:
def s(a):
print('-->start')
b=yield a
print("recived",a,b)
c=yield a+b
print('recived0',a,b,c)
sc=s(5) -->主线程生成生成器 args-->5
aa=next(sc) next 返回yield结果
print(aa) -->5
bb=sc.send(6) 返回6给b,不过先yield返回a
print(bb)
cc=sc.send(7) 返回7给c,不过先yield返回a+b=11
print(cc)
next 返回一个结果 即返回的是yield后面的程序/变量
send赋值是给yield前面的变量
协程中止
生成器最后一次发出stopIteration异常的情况是正常的异常对象value保存返回值
例:
def s():
for i in 'AB':
yield i
print(list(s()))
def s():
yield from 'AB'
print(list(s()))
委派生成器
例:
from collection import namedtuple
Resclass= namedtuple('Res','count average')
子生成器
def averager():
total=0.0
count=0
average=None
while true:
term=yield
if term is None:
break
total+=term
count+=1
average=total/count
return Resclass(count,average)
asynico(异步io包)本身是一个消息循环
1.创建消息循环
2.把协程引入
3.关闭
例:
import threading
import asynico
@asynico.coroutine
def hello():
print('hello world!(%s)'% threading.currentThread())
print('Start....(%s)'%threading.currentThread())
yield from asynico.sleep(10)
print('Done....(%s)'%threading.currentThread())
print('hello again(%s)'%threading.currentThread())
loop=asynico.get_event_loop()
tasks=[hello(),hello()]
loop.run_until)complete(asynico.wait(tasks))
loop.close()
aiohttp案例
例:
import asynico
from aiohttp import web
ansy def index(request):
await asynico.sleep(0.5)
text='<h1>hello,%s!<h1>'%request.match_info['name']
return web.response(body=text.encode('utf-8'))
ansy def init(loop):
app=web.application(loop=loop)
app.router_add_route('GET','/',index)
app.router_add_route('GET','/hello/{name}',hello)
srv=await.loop_create_server(app.make_handler(),'127.0.0.1',8000)
print ('server started at http://127.0.0.1:8000')
return srv
loop=asynico.get_event_loop()
loop.run_until_complete(init(loop))
loop.run_forever()
concurrent.futures (并发执行,类似于其他语言的线程池,帮助我们重复和管理路线提高响应速度)
利用multiprocessing实现真正并行
concurrent.futures (TheadPoolExecutor/ProcessPoolExector)
例:
Submit(fnc,args,kwargs):
from concurrent.futures import TheadPoolExecutor
import time
def return _future(msg)
time.sleep(3)
return msg
pool=TheadPoolExecutor(max_workers=2)
f1=pool.Submit(return_futures,"hello")
f1=pool.Submit(return_futures,"world")
print (f1.done())
time.sleep(3)
print(f2.done())
print (f1.result())
print (f2.result())
结构化文件存储(XML/JSON)
为了解决不同设备系统(windows/linux/mac)的信息交换问题
XML为可扩展标记语言(用户可以自己定义需要的标记)(标记语言是语言中使用<>括起来的文本字符串)
XML描述的是数据本身即数据的结构,语义
XML的构成
1.处理指令->一个文件只有一个处理指令/一般由版本、编码选择构成
<?xml version='1.0' encording='utf-8'?>
2.根元素->一个文件只有一个根元素,树形结构
3.子元素->一个根元素下,可以有多个相同元素并行
4.属性->对标签本身进行说明 type、location、date
5.内容->标签所存储的信息
6.注释->标签里面不能有注释 注释的方式 1.<name><!__名字__></name> 2.<!---名字--->
例子:
<school>
<student1>
<age></age>
<name></name>
</student1>
<student2>
<age></age>
<name></name>
</student2>
<student3>
<age></age>
<name></name>
</student3>
</school>
这里三个student是平行关系
并归冲突问题<student>
<name>'A'</name>
<age>'18'</age>
</student>
<room>
<name>'A-2'</name>
</room>
<school>
<name>'A'</name>
<name>'A-2'</name>
</school>
#子元素里面的<name>重名,需要为冲突元素添加命名空间
<school xmlns:student="http://my_student" xmlns:room="http://my_room">
<student:Name>'A'</student:Name>
<room:Name>'A-2'<room:Name>
</school>
XML文件的访问:
1.读取XML文件——>SAX、Dom (工业标准的解析xml方法)
2.SAX——>simple API for XML 基于事件驱动
3.Dom——>1.W3c规定的XML编程接口
2.一个XML文件在缓存中以树形结构保存
用途:定位浏览XML任何一个节点信息,添加删除相应的内容
4.Dom分为minidom/etree
4.1 minidom.parse(filename):
#加载读取的XML文件
4.2 doc.documentElement:
#获取XML文档对象
4.3 node.getAttribute():
#获得XML节点属性
4.4 node.getElementByTagName():
#得到一个节点对象集合
4.5 node.childNodes:
#得到所有的子节点
4.6 node.childNodes[index].nodeValue:
#获得单个节点,0为第一个节点信息
XML文件的写入:
1.Element.set 更改
2.Element.append 添加
3.Element.remove 删除
例子:
import xml.etree.ElementTree as et
str=et.Element("Student")——>生成根元素Student
name=et.SubElement(str,'Name') ——>子元素Name
name.attrib={'lang','en'}
name.text='名字'
age=et.SubElement(str,'age')——>子元素age
age.text=18
et.dump(str)——>生成文件
XML文件的读取: #在使用xml.dom.minidom时,使用parse()或者CreateDocument()返回对象 ————>创建一个指定类型的xml对象
例子:
import xml.dom.minidom #Node是节点,Element是元素
from xml.dom.minidom import *
DomTree=xml.dom.minidom.parse("Student.xml") # 利用minidom打开XML文件
doc=DomTree.documentElement #利用文档格式获得DomTree
for ele in doc.childNodes:
if ele.nodename=="Teacher":
print ("....Node:{0}....".format(ele.nodename))
childs=ele.childNodes
for child in childs:
ifchild.nodename="Name":
print("Name:{0}".format(child.childNodes[0].data))
ifchild.nodename="Moblie":
print("Name:{0}".format(child.childNodes[0].data))
ifchild.nodename="Age":
print("Name:{0}".format(child.childNodes[0].data))
etree:以树形结构来表示xml
- root.getiterator #得到相应的可迭代node集合
- find(node_name) #查找指定node_name的节点,返回一个node
- root.finally(node_name) #返回多个node_name节点
- node.tag #node对应的tagname tag为标签
- node.text #node的文本值
- node.attrib #是node属性的字典类型内容 attrib是修改
- 每个node都有nodename、nodevalue、nodeType、attrib
例子:
import xml.etree.ElementTree
root=xml.dom.minidom.parse("Student.xml") #返回对象
nodes=root.getiterator()
for node in nodes:
print ("{0},--{1}".format(node.tag,node.text))
ele_teacher=root.find("Teacher") #利用find / findall
print ("{0}--{1}".format(ele_teacher.tag,ele_teacher.text))
ele_stus=root.findall("Student")
for ele in ele_stus:
print ("{0}-{1}".format(ele.tag,ele.text))
for sub in ele.getiterator():
if sub.tag=="Name"
if "other" in sub.attrib.key():
print (sub.attrib['other'])
例子:
from xml.etree import ElementTree as et
tree=et.parse("student.xml")
root=tree.getroot()
for e in root.iter('Name'):
print (e.text)
for stu in root.iter('Student'):
name=stu.find('Name')
if name==None:
name.set('test',name.text*2)
stu=root.find('Student')
e=et.ElementTree('ADDer')
e.attrib={'a','b'}
e.text="我加的"
stu.append(e)
tree.write('to_edit_xml')
#attributes 属性节点
#Element 属性对象
1.tag:string 对象代表种类 就是子元素名
2.attrib:dict对象 附有属性
3.text:string对象,element内容
4.tail:element闭合后内容
例子:
<student>
<name> 123</name>
</student>
import xml.etree.ElementTree at et
etree=et.ElementTree() #在内存中创建一个空的文档
e=et.ElementTree('Student')
etree.setroot(e) #将e作为根元素
e_name=et.SubElement(e,'Name')
e_name.text='123'
etree.write('ABC.xml')
xml中5个预定义的实体引用
⁢ <
> >
& &
&apos '
" "
例子:
import xml.etree.ElementTree / import xml.dom.minidom
import xml.etree.ElementTree as et
tree=et.parse("xxx.xml")
root=tree.getroot() #获取根元素
for child in root:
print(child.tag,child.attrib)
print(child.tag,child.get('name')) #将属性额value值直接显示出来
root.getchildren() #直接将子元素一个一个地显示出来,附上地址
#ElementTree树可以根据索引值查找值,root[0][0].text ——>根元素下第一个子元素的第一个标签的文本
#root.find/root.finally 返回第一个以tag寻找的子元素 / 返回全部以tag寻找的子元素
import xml.dom.minidom 利用dom写xml文件
dom=minidom.document() #创建dom树对象
root_node=dom.creatElement('root') #创建根节点
dom.appendchild(root_node) #将新创建的子节点加载到dom中
root_node.setAttribute('age',18) #子节点的键值对
root_text=dom.creatTextNode('xml写的文件')
dom.appendchild(root_text)
JSON:格式是键值对形式产生的数据集
json<——>python 之间的转换
1.json.dump() python——>json (对数据进行编码,将内容写入文件)
2.json.loads() json——>python (对数据进行解码,json文件读入python)
json<——>python 之间的格式对应
1.字符串<——>字符串
2.数字 <——>数字
3.队列 <——>list
4.对象 <——>dict
5.布尔值<——>布尔值
例子:
(1.)
import json
student={
"name":"hbg",
"age":"18",
"mobile":110
}
print type(student)
stu_json=json.dumps(student) #将字典类型数据写入json文件
print (type(stu_json))
print ("json对象:{0}".format(stu_json))
stu_dict=json.loads(stu_json)
print (type(stu_dict))
print (stu_dict)
(2.)
import json
data={"name":"hahaha",
"age":12,
}
with open ("student.json","w") as f:
json.dump(data,f)
with open ("student.json",'r') as f:
d=json.loads(f)
print(d)
RE(正则表达式)
- 使用complie将表示正则的字符串编译成pattern对象
- 通过pattern对象将与文本进行匹配,获得一个Match对象
- 最后是用Match的属性和方法获得信息
- 关于正则表达式的贪婪性和非贪婪性
- 贪婪性:
尽可能多的匹配(*)表示贪婪
- 非贪婪性
找到符合条件的最小内容即可(?)正则默认使用贪婪匹配
match例子:
import re
p=re.compile(r'\d+')
m=p.match("one123456798two",3,6) #match参数可输入查找的起始位置
print (m) #结果显示 <_sre.SRE_Match object; span=(3, 6), match='123'>
print(m[0])
print(m.start(0))
print(m.end(0))
search例子:
p = re.compile(r'([a-z]+) ([a-z]+)')
m = p.search("I love you xiaosb")
print(m.group(1))
print (m.start(1))
print (m.end(1))
print(m.group(0))
print (m.start(0))
print (m.end(0))
'''
love
2
6
love you
2
10
'''
search例子:
import re
p=compile(r'\d+')
m=p.search("one123two456")
print(m.group()) #123
rst=p.findall("one123two456three798") #['123','456','798'] 最终以列表的方式呈现数据
Sub替换例子:
import re
p=re.compile(r'(\w+)(\w+)')
s="hello 123 wang 456 xiaojing,i love you "
rst=p.sub(r"hello world",s)
#最终结果: hello world 123 wang 456 xiaojing,i love you
X-path
- 在xml语言中查找信息的一套语言/根据xml的元素成员属性进行遍历
- 选取节点:nodename 选取节点的所有子节点
- '/':从根节点开始选取
- '//':选取节点,不考虑位置 (多个节点组成列表返回)
- '.':选取当前节点
- '..':选取当前节点的父节点
- '@':选取属性
例子:
<School>
<Teacher>
</Teacher>
<Student1>
</Student1>
<Student2>
</Student2>
</School>
- School/Teacher #返回Teacher节点
- //Student #返回两个平级的Student
- School//age #选取School节点下的age节点
- //@other #选取other属性
- Age[@Detail] #选取带有属性Detail的Age属性
- /School/Student[1] #School下面的第一个Student节点
- /School/Student[last()] #School下面的最后一个Student节点
- /School/Student[position()<3] #School下前2个Student节点
- //Student[@Scroe]/Age #选取带属性Scroe的Student节点的子节点Age
网络编程
Socket编程
- Socket(套接字):是一个网络通信的端点,实现不同主机间的通信.
- 通过Ip+port发送消息的机制
- 分为UDP/TCP编程发送
- 分为client客户端/server服务端
UDP编程
- Server端程序
1.建立Socket,负责具体通信的一个实例
2.绑定(bind)创建的Socket指派固定的ip和port
3.接受对方发送内容
4.给对方发反馈(可不执行)
5.服务器程序要求永久运行,一般使用死循环.
- Client端流程
1.建立通信Socket
2.发送内容到指定服务器
3.接受服务器的反馈内容
UDP例子:
import socket
def ServerFunction(): #模拟服务器
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #创建Socket实例
#1.建立Socket
#2.绑定ip+port,地址是一个tuple类型
address=("127.0.0.1",7852)
sock.bind(address)
data,address=sock.recvfrom(500)
'''
recvfrom返回一个tuple类型,data是数据,address是地址。500是指缓冲区的大小
'''
text=data.decode()
print (text)
rsp="I reciverd the message"
data=rsp.encode()
sock.sendto(data,address)
if __name__=="__main__":
while True:
print ("starting")
ServerFunction()
print ("ending......")
import socket
def ClientFunction(): #模拟服务器
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #创建Socket实例
#1.建立Socket
#2.绑定ip+port,地址是一个tuple类型
text="I Love you "
data=text.encode()
sock.sendto(data,("127.0.0.1",7852))
data,address=sock.recvfrom(200)
data=data.decode()
print (data)
if __name__=="__main__":
ClientFunction()
TCP编程
- 面向连接的传输,即每次传输前会建立一个连接
- 客户端和服务器,两个程序需要编写
- 服务端server的编写流程
- 建立Socket实例,这个socket只负责接受对方的请求
- 绑定(bind)ip+port
- 监听接入访问的socket
- 接受访问的socket,可以理解为接受访问即建立了一个通讯的连接通道
- 接受对方发送的内容,利用接收的socket接收内容
- 如果有必要,给对方发送反馈消息
- 关闭连接通道
- 客户端Client的编程流程
- 建立Socket实例
- 连接对方,请求跟对方建立联系
- 发送内容到指定服务器
- 接受对方的反馈
- 关闭连接通道
例子:
import socket
def Tcp_server():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建Socket实例,表明为tcp
address=("127.0.0.1",8998)
sock.bind(address) #socket绑定
sock.listen() #监听介入访问的socket
while True:
skt,addr=sock.accept() #接受客户端连接
msg=skt.recv(500) #对话接收
msg.decode()
rst="Received msg {0} from {1}".format(msg,addr)
print(rst)
skt.send(rst.encode()) #对话发送
skt.close()
if __name__=="__main__":
print ("Start Server")
Tcp_server()
print("end Server")
import socket
def Tcp_Client():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
addr=("127.0.0.1",8998)
sock.connect(addr) #建立连接
msg="I love you "
sock.send(msg.encode())
rst=sock.recv(500)
print (rst.decode())
sock.close()
if __name__=="__main__":
Tcp_Client()
FTP编程:(FiletransferProtocal)
- 定制一些特殊的上传下载文件的服务
- 登录FTP的账号分类:
- Real账号:注册账号
- Guest账号:临时对某类人进行授权
- Anonymous账号:匿名账户,适用于所有人
- FTP工作流程:
- 客户端连接远程主机上的FTP服务器
- 客户端输入用户名和密码(anonymous和电子邮件地址)
- 客户端和服务器进行各种文件传输接信息查询工作
- 客户端从远程FTP服务器退出,结束传输
例子:
import ftplib
import os
import socket
HOST="ftp.acc.umu.se"
DIR="public/EFLIB"
File='README'
try:
f=ftplib.FTP()#客户端远程连接FTP服务器
f.set_debuglevel(2)#设置调试级别
f.connect(HOST) #连接主机地址
except Exception as e:
print (e)
exit()
print("XXXconnent to host{0}".format(HOST))
try:
f.login()#如果没有输入用户信息则默认使用匿名
except Exception as e:
print (e)
exit()
print ("***logined in as 'anoymous'")
try:
f.cwd(DIR)
except Exception as e:
print (e)
exit()
print ("***change DIR to {}".format(DIR))
try:
f.retrbinary('RETR{0}'.format(File),open(File,'wb'.write)) #从服务器下载文件第一个参数是ftp参数,第二个参数是回调参数
except Exception as e:
print (e)
exit()
f.quit() #运行回调函数
运行结果:
*get* '220 Please use http://ftp.acc.umu.se/ whenever possible.\n'
*resp* '220 Please use http://ftp.acc.umu.se/ whenever possible.'
XXXconnent to hostftp.acc.umu.se
*cmd* 'USER anonymous'
*put* 'USER anonymous\r\n'
*get* '331 Please specify the password.\n'
*resp* '331 Please specify the password.'
*cmd* 'PASS **********'
*put* 'PASS **********\r\n'
*get* '230 Login successful.\n'
*resp* '230 Login successful.'
***logined in as 'anoymous'
*cmd* 'CWD public/EFLIB'
*put* 'CWD public/EFLIB\r\n'
*get* '550 Failed to change directory.\n'
*resp* '550 Failed to change directory.'
550 Failed to change directory.
Mail编程:
邮件工作流程:
- MUA(MailUserAgent)邮件用户代理
- MTA(MailTransferAgent)邮件传输代理
- MDA(MailDiliveryAgent)邮件投递代理
1.MUA-->MTA 将邮件传输在服务器上
2.qqMTA-->sinaMTA 用qq的服务器将文件传输到新浪的服务器上
3.sinaMTA-->sinaMDA 此时邮件已被投放在用户邮箱里
4.sinaMDA-->MUA(foxmail/outlook)将邮件下载到本地电脑上
程序发送:MUA-->MTA with SMTP(SimplemailTransferprotocal)
程序接受:MDA-->MUA with PoP3 and IMAP (POP3负责接收邮件)
例子:
import smtplib
from email.mime.text import MIMETEXT
msg=MIETEXT("I love 二狗子","plain","utf-8") #MIMETEXT(1.邮件内容,2.MIME子类型用plain表示,3.邮件编码格式)
from_address="809624748@qq.com"
from_password="qq邮箱的授权码"
smtp_srv="smtp.qq.com"
try:
srv=smtplib.SMTP_SSL(smtp_srv.encode(),465) #1.服务器格式必须是bytes格式,必须编码 2. 服务器接受访问端口为465
srv.login(from_address,from_password)
srv.sendmail(from_address,[目标地址],msg.as_string())
srv.quit()
except Exception as e:
print (e)
例子:
HTML格式发文件,MIME的子类型为html
msg<-->mail_contect='''
<!DocType html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<h1>这是一封HTML格式的文件</h1>
</body>
</html>
'''
msg=MIETEXT(mail_contect,"plain","utf-8")
例子:
发送带附件的邮件
- 可以把邮件看作是一个文本的邮件加一个附件的合体
- 一封邮件如果涉及到多个部分,就需要使用MIMEMultipart格式构建
- 具体的操作为减价一个MIMEtext作为正文,添加一个MIMEtext/MIMEBase作为附件
'''
from email.mime.multioart import MIMEBase,MIMEMultipart #构建技术邮件使用
mail_mul=MIMEText() #实例化
mail_mul.attach(mail_text)
m=MIMEText()
m["content-Type"]="application/octet-stream"
m["content-Disposition"]="attachment;filename=''"
mail_mul.attach(m)