python笔记

这是一份全面的Python编程笔记,涵盖了从基础语法、数据结构到高级特性,包括函数、字典、集合、文件操作、异常处理、模块、图形界面编程等内容,适合初学者系统学习。

这篇笔记是去年寒假看视频的时候总结的,比较杂,算是对python的初步了解,先贴出来,以后有空再做系统的整理和补充。


杂项

0、字符串前面加r 原始字符串 省去所有转义 但最后不能有反斜杠
三重引号字符串”“” “”” 打印长字符串


1、if while else 后面要加冒号


2、isinstance 测试类型 isinstance(a,int)为true表示a是int,false表示不是
type也可以用来查看类型
num = 1
type(num) # 结果是int


3、//表示地板除法 整数除整数 为整数 向下取整
/为真正的除法
** 次幂运算 比左侧的数优先级高 比右侧的优先级低 -3**2 = -(3**2) -3 ** -2=-(3**(-2))
非0都是true,true==1,false==0
2<3<4 <==> 2<3 and 3<4
优先级
幂>正负号>算数操作>比较>逻辑


4、elif 就是 C的else if
python可以避免悬挂else if 和 else不匹配的情况
x if 条件 else y
if x < y:
small = x
else:
small = y


5、断言 assert 自爆函数 当后边条件为false时 程序报错 当后面是true 就pass 相当于是检查点


6、python的for循环更加智能和强大 会自动调用迭代器的next并捕获迭代器的结束

for 目标 in 表达式:
    循环体 

7、for的小伙伴 range
range([start,]stop[,step=1])
默认从0开始,步长为1,不包含stop的那个数

>>>for i in range(2,10,2):
    print(i)
2
4
6
8
>>>

8、break 终止当前循环
continue 终止本轮循环并开始下一轮,首先要测试循环条件,满足则开始,否则会推出循环
会被看做假的内容:
False、None、0、”“、”、()、[]、{},其余都是真


9、列表

list,可以把任何数据类型打包进列表
创建普通列表 number = [1,2,3,4,5]
创建混合列表 mixture = [1,2.3,’4.5’,[6,7,8]]
创建空列表 empty=[]
添加元素 append() extend() insert()

>>>number.append(6) #只能一个个的加入
>>>number.extend([7,8]) #使用一个列表扩展另一个列表
>>>number.insert(0,'0') #在第0个位置插入元素'0'

获取元素 number[5]索引值
删除元素 remove(1) #删掉元素1 当要删除的元素不在列表中则会报错
del number[1] #不是一个函数 是一个语句 删掉指定元素 也可以删掉整个列表
pop() #不带参数 则会返回最后一个参数并删掉 列表原理是堆栈
pop(1) #也可以带参数 取出并删掉第1个元素
列表分片 slice 一次性获取多个元素

>>>number[1:3] #分出两个元素 从1到3 不包含3 得到原列表的一个拷贝 :前省略表示从头,之后省略表示到尾
>>>member=number[:]#获得完整拷贝 互不影响 实实在在的拷贝一次 
>>>member=number #会受到number修改的影响 指定另外一个名字 只是相当于再添加一个名字

列表删除 clear() 清空全部元素 但列表还在
列表复制 copy()
列表比较操作 从第一个开始比较 第0个赢了整体就赢了
列表逻辑操作 和其他的一样
列表运算操作 值拼接在一起 相当于extend方法 加号两边类型必须一致
列表重复操作 乘号* 将原列表重复多次接在后面
列表成员关系操作 in 和 not in ,列表中的列表的成员不能直接用 in /not in

>>>list = [1,[9,10],100]
>>>9 in list[1]
True

类比访问二维数组的方法访问上面的9 ==> list[1][1]=9
列表的小伙伴
计算参数在列表中出现的次数 count()
返回参数在列表中第一次出现的位置 index() #后接第二第三两个参数可以卡住范围
列表整体镜像 最前的排最后 最后排最前 reverse()
用指定方式对列表排序 sort(func,key,reverse) #默认是(升序排列,归并排序,false)
*列表推导式
[有关A的表达式 for A in B]
list1 = [x**2 for x in range(10)]
list1 = [0,1,4,9,16,25,36,49,64,81]
类似还有list1 = [(x, y) for x in range(10) for y in range(10) if x%2==0 if y%2!=0]


10、元组

tuple 不可改变的类型 定义之后不可改变
与列表非常相似,
创建和访问元组 用小括号

>>>tuple1 = (1,2,3,4)
>>>tuple2 = () #创建空元组
>>>tuple3 = 1#创建元组

用索引访问
分片的办法与列表相同
元素不可以修改 tuple[1] = 2 会报错
加上小括号也不一定是元组
没有小括号也不一定不是元组
逗号才是关键

>>>8*(8,) # 重复8次

添加元素 相当于在原有基础上插入新元素,构成新元组,在复制回原元组

>>> temp = (1,2,3)
>>> temp = temp[:1]+(1.5,)+temp[1:] #括号和逗号都是关键!`原元组还在但是没有标签指向他,过段时间会被删掉
>>> temp
(1, 1.5, 2, 3)

删除元素 del temp #删除整个元组
拼接操作符 、重复操作符、成员操作符、逻辑操作符和列表都是相似


11、字符串

str
str1 = ‘1234567890’
str1[:3]= ‘123’
str1[3] = ‘4’ #其实是个子字符串
str1[:3]+’66666’+str1[3:] #插入的方法和元组类似
str的很多方法方法,返回一个新的字符串 原字符串没有被改变
join 把子字符串作为分隔符插入到字符串中

>>>str1.join('x') #str1就会变成1x2x3x4

partition(sub) 转换成3元组(sub之前,sub,sub之后)
split以空格来分片


12、格式化字符串
format方法 参数 位置参数和格式化参数 replacement

>>> "{0} love {1}".format("I","U")
'I love U'
>>> "{{0}}".format("x") #两层括号 可以打印出括号
'{0}'
>>> '{0:.2f}{1}'.format(12.3456,'GB') #:表示表示一个是字符串的开始 .2表示四舍五入保留两位小数
'12.35GB'

13、序列

列表、元组、字符串 都是序列
list() tuple() str()带参数则是将所给的序列转换为对应的类型
len() 求长度
max() min() 返回序列的最大值 最小值
sum() 求和
sorted() 排序
reversed() 返回迭代器对象 用list()在生成一次就可以显示了
enumerate()枚举 把每一个元素变成一个元组,在元素前插入索引值构成一个元组
zip() 返回各个参数的对应索引位置构成的元组组成的的序列

>>> a=[1,2,3,4,5]
>>> b=[1,2,3]
>>> zip(a,b)
<zip object at 0x000000DED512A908>
>>> list(zip(a,b))
[(1, 1), (2, 2), (3, 3)]

14、函数

函数定义

>>> def MyFunc(num1,num2):
    print('-------------')
    print('first func')
    print('-------------')
    return(num1+num2)

>>>

函数调用

>>> MyFunc(5,6)
-------------
first func
-------------
11
>>>

调用时向上寻找函数定义的位置

函数文档

不同于注释
函数下方的一个字符串 functionNmae.doc可以打印出函数文档,用help也可以访问到函数文档

关键字参数

给参数下个定义(形参=实参 eg. func(name = “LYY”,age=21)),
顺序改变就不会出现问题
可以设置默认参数值,使得不用输入参数也可以有默认值

收集参数

在参数前面加上星号,就变成了可变参数。如果有普通参数和收集参数混合,则需要指定关键字参数

>>> def prac(*para,exp = 8):
    print('length',len(para))
    print('second',para[1])
    print(exp)


>>> prac(1,(1,2,3),'134',exp = [1,2,3])
length 3
second (1, 2, 3)
[1, 2, 3]
>>> 

函数和过程

有返回值是函数
无返回值是过程 python原则上是没有过程的
局部变量和全局变量的区别和操作和C类似
函数内部修改了全局变量的话,会创建一个同名的局部变量,与外部的全局变量互不影响,所以内部修改不会影响到外面
不要试图在函数内部修改它,没有用,只能访问
用global修饰变量,则可以修改

内嵌函数

函数内部定义的函数
内部函数整个作用于都在外部函数之内

闭包

一种编程范式(面向过程、面向对象)
python几乎所有东西都是对象
对于在在一个内部函数里,对外部作用域的变量进行引用,则内部函数是一个闭包

>>> def FuncX(x):
    def FuncY(y):
        return x * y
    return FuncY

>>> i = FuncX(8)
>>> i
<function FuncX.<locals>.FuncY at 0x000000DED511EBF8>
>>> type(i)
<class 'function'>
>>> i(5)
40
>>> FuncX(10)(7) #直接输入两个参数
70
>>> 

>>> def Fun1():
    x = [5] #用元组存储数据不存储在栈上 不会被屏蔽
    def Fun2():
        x[0]*=x[0]
        return x[0]
    return Fun2()

>>> Fun1()
25
>>>

>>> def Fun1():
    x = 5
    def Fun2():
        nonlocal x #声明nonlocal 不会被屏蔽
        x*=x
        return x
    return Fun2()

>>> Fun1()
25
>>>

nonlocal 可以让之前的屏蔽取消 将外部变量的修改保存下来

匿名函数

lambda表达式
冒号前是参数列表 之后是函数体

>>> lambda x : 2 * x + 1
<function <lambda> at 0x000000DED511EF28>
>>> f = lambda x : 2 * x + 1
>>> f(5)
11
>>>

过滤器函数 filter

>>> def odd(x):#函数实现
    return x%2

>>> temp = range(10)
>>> show = filter(odd,temp)
>>> list(show)
[1, 3, 5, 7, 9]
>>> list(filter(lambda x : x % 2,range(10)))#一行实现
[1, 3, 5, 7, 9]
>>> 

映射 map

>>> list(map(lambda x : x * 2,range(10)))
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>>

将传入的值依次进行迭代


15、递归
Python递归最多100层


16、字典

标志是 {键:值,键:值}
创建和访问字典

>>> dict1 = {'A':'aaa','B':'bbb','C':'ccc','D':'ddd'}
>>> print(dict1['A'])
aaa

也可以用元组定义

dict2 = dict((('E','eee'),('F','fff')))

添加元素 dict2[‘G’] = ‘ggg’

fromkeys 创建并返回一个新的字典

>>> dict1.fromkeys((1,2,3))
{1: None, 2: None, 3: None}
>>> dict1.fromkeys((1,2,3),'1')
{1: '1', 2: '1', 3: '1'}


>>> for eachKey in dict1.keys():
    print(eachKey)  
4
>>> for eachValue in dict1.values():
    print(eachValue)    
1
>>> for eachItem in dict1.items():
    print(eachItem) 
(4, '1')

get方法

更安全 如果试图访问不存在的项 则只返回None(或者自己设置的值) 而不是报错
get(5,’不存在’) 则就会返回“不存在”
对于in /not in
字典查找的是键不是值
序列是查找值
clear()清空字典
copy() 浅拷贝 真正复制一次 地址会变
= 直接赋值 多加了一个指向的标签 地址不变
pop() 弹出键对应的值 并在原字典中删掉
popitem() 弹出最后一个
setdefault()
update() 更新信息 参数是一个字典

>>> a = {1:'one',2:'two',3:'three'}#定义字典
>>> c=a #直接赋值
>>> c[4] = 'four' #插入项目 之后a和c都变成 {1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> a.popitem() #弹出最后一项
(1, 'one')
>>> c.popitem() #弹出最后一项 可以看到 a和c 实际上是一个字典 修改会相互影响
(2, 'two')
>>> c #popitem之后成为如下样子 a也一样 
{3: 'three', 4: 'four'}
>>> a.setdefault(5) #设置默认值 键为5 值为None
>>> a
{3: 'three', 4: 'four', 5: None}
>>> a.setdefault(5,'five') #这个语句并不能改变已有项目的值
>>> a
{3: 'three', 4: 'four', 5: None}
>>> a[5] = 'five' #可以更新项目
>>> a
{3: 'three', 4: 'four', 5: 'five'}
>>> a.pop(4) #pop掉指定位置的项目
'four'
>>> a
{3: 'three', 5: 'five'}
>>> b = {6:'six'} #创建新字典
>>> a.update(b) #用该字典更新a
>>> a
{3: 'three', 5: 'five', 6: 'six'}

17、集合

标志{,,,,}
元素的唯一性,会剔除所有重复的元素,但它是无序的

创建集合

>>> num1 = {1,2,3,4,5} #直接创建
>>> type(num1)
<class 'set'>
>>> set1 = set([1,3,5,5,6,7]) #用工厂函数
>>> set1
{1, 3, 5, 6, 7}
>>> num2 = [1,1,1,3,4,4,5,6,7,4,4,2,1,0]
>>> num2 = list(set(num2)) #去除重复元素
>>> num2
[0, 1, 2, 3, 4, 5, 6, 7]

不可变集合

frozenset()

>>> num3 = frozenset([1,2,3,4,5]) 
>>> num3.add(0) #会报错

集合是无序的,不能用索引访问

集合(s).方法名等价符号方法说明
s.issubset(t)s <= t子集测试(允许不严格意义上的子集):s 中所有的元素都是 t 的成员
s < t子集测试(严格意义上):s != t 而且 s 中所有的元素都是 t 的成员
s.issuperset(t)s >= t超集测试(允许不严格意义上的超集):t 中所有的元素都是 s 的成员
s > t超集测试(严格意义上):s != t 而且 t 中所有的元素都是 s 的成员
s.union(t)s | t合并操作:s “或” t 中的元素
s.intersection(t)s & t交集操作:s “与” t 中的元素
s.differences - t差分操作:在 s 中存在,在 t 中不存在的元素
s.symmetric_difference(t)s ^ t对称差分操作:s “或” t 中的元素,但不是 s 和 t 共有的元素
s.copy()返回 s 的拷贝(浅复制)
以下方法仅适用于可变集合
s.updates |= t将 t 中的元素添加到 s 中
s.intersection_update(t)s &= t交集修改操作:s 中仅包括 s 和 t 中共有的成员
s.difference_update(t)s -= t差修改操作:s 中包括仅属于 s 但不属于 t 的成员
s.symmetric_difference_update(t)s ^= t对称差分修改操作:s 中包括仅属于 s 或仅属于 t 的成员
s.add(obj)加操作:将 obj 添加到 s
s.remove(obj)删除操作:将 obj 从 s 中删除,如果 s 中不存在 obj,将引发异常
s.discard(obj)丢弃操作:将 obj 从 s 中删除,如果 s 中不存在 obj,也没事儿^_^
s.pop()弹出操作:移除并返回 s 中的任意一个元素
s.clear()清除操作:清除 s 中的所有元素

18、文件

打开文件 open(文件名,打开方式,buffering,encoding) 返回一个文件对象
有写入操作的话 应当及时关闭文件 f.close()
readline() 写入模式打开,如果存在 追加写
read() 读取指定字节
f.tell() 获取当前指针位置
f.seek() 按字节为单位定位指针,如果出现在汉字字符的中间位置 则会出现解码错误
list(f) 转化成列表
迭代打印出文件的每一行

for each_line in f:
    print(each_line)
for i in range(line_num):
    print(f.readline(),end='')

19、模块

是一种封装,容器是对数据的封装,函数是对语句的封装,类是对方法和属性的封装
模块就是程序
一个.py 就是一个模块
使用模块内的东西 需要有命名空间
包含所有的函数和变量的文件
可以被别的程序import
导入方法 import balabalabala as bala
拆分程序便于阅读,实现代码重用
if __name__ == ‘__main__’ #如果当前模块是作为导入 则name值是模块名 而不是main
test() #测试时才调用的语句块
让python知道 当前程序是作为模块导入还是作为主程序

搜索路径

导入模块时 python搜索路径 找到就导入 找不到则导入失败
sys.path 显示寻找的路径列表
推荐放在C:\python\lin\site-packages目录下
可以用append加到路径列表中
sys.path.append(“A:\\bbb\\ccc”)

包(package)

把模块分类存放在不同的文件夹
创建一个文件夹
在文件夹中创建一个__init__.py模块 可以为空 告诉python把这个文件夹当做包来看待
把其他模块放进去
导入的时候 import 包名.模块名 as balabala
pypi.python.org
PEP
先import一个模块
print(模块名.__doc__)
dir(模块名)
__all__属性下的方法是作者希望外部调用的方法
from 模块名 import * 只会导入 all属性的方法
__file__查看模块源代码位置
help(模块名)

os模块

getcwd() 返回当前工作目录
chdir(path) 改变工作目录
listdir(path=’.’)列举目录下的文件名
mkdir(path) 创建目录
makedirs(path) 递归创建多层目录
remove(path) 删除文件
rmdir(path) 删除单层目录 如果目录不为空 则会报错
removedirs(path) 递归删除目录
rename(old,new) 重命名
system(cmd) 运行系统的shell命令

curdir 指代当前目录 .
pardir 指代上级目录 ..
sep 指代路径分隔符
linesep指代行终止符
name 指代操作系统

os.path模块

basename(path) 去掉目录路径 返回文件名
dirname(path) 去掉文件名 返回路径
join(path1[,path2,[,…]])将path1,path2用\组合成路径名
split 分割文件名和路径
splitext 分离文件名和扩展名
getsize 返回文件尺寸,单位是字节
getatime 返回文件最近访问时间
getctime 创建时间
getmtime 最新修改时间

可以用time模块的gmtime() localtime()换算时间

exists(path) 判断指定路径(目录/文件)是否存在
isabs(path) 判断是否为绝对路径
isdir(path) 判断指定路径是否存在且是一个目录
isfile(path) 判断指定路径是否存在且是一个文件
islink(path) 判断指定路径是否存在且是一个符号链接/快捷方式
ismount(path)判断指定路径是否存在且是一个挂载点/盘符
samefile(path1,path2) 判断两个路径是否指向同一个文件

pickle模块

pickle_file = open('my_list.pkl','wb')
pickle.dump(my_list,pickle_file)#存储
pickle_file.close()
pickle_file = open('my_list.pkl','rb')
my_list2 = pickle.load(pickle_file) #读取

将大量的字典或者常量 写入pkl文件


20、异常处理

常见异常汇总

名称说明
AssertionError断言语句失败
AttributeError尝试访问未知的对象属性
EOFError用户输入文件末尾标志EOF(Ctrl+d)
FloatingPointError浮点计算错误
GeneratorExitgenerator.close()方法被调用的时候
ImportError导入模块失败的时候
IndexError索引超出序列的范围
KeyError字典中查找一个不存在的关键字
KeyboardInterrupt用户输入中断键(Ctrl+c)
MemoryError内存溢出(可通过删除对象释放内存)
NameError尝试访问一个不存在的变量
NotImplementedError尚未实现的方法
OSError操作系统产生的异常(例如打开一个不存在的文件)
OverflowError数值运算超出最大限制
ReferenceError弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
RuntimeError一般的运行时错误
StopIteration迭代器没有更多的值
SyntaxErrorPython的语法错误
IndentationError缩进错误
TabErrorTab和空格混合使用
SystemErrorPython编译器系统错误
SystemExitPython编译器进程被关闭
TypeError不同类型间的无效操作
UnboundLocalError访问一个未初始化的本地变量(NameError的子类)
UnicodeErrorUnicode相关的错误(ValueError的子类)
UnicodeEncodeErrorUnicode编码时的错误(UnicodeError的子类)
UnicodeDecodeErrorUnicode解码时的错误(UnicodeError的子类)
UnicodeTranslateErrorUnicode转换时的错误(UnicodeError的子类)
ValueError传入无效的参数
ZeroDivisionError除数为零

异常检测

try:
    检测范围
except (Exception1[,exception2,...])[as reason]:
    异常的处理代码
finnally:
    无论如何都会被执行的代码

try语句块内一旦出现异常,后续代码将不会执行,报错后跳到finally
对多个异常作统一处理把 except后面的异常类别写成元组
try内没有错误 执行完了以后 执行finally部分

raise语句

引发一个异常

>>> raise ZeroDivisionError('除数为0的异常')
Traceback (most recent call last):
  File "<pyshell#57>", line 1, in <module>
    raise ZeroDivisionError('除数为0的异常')
ZeroDivisionError: 除数为0的异常
>>> 

21、else语句

*要么怎样,要么不怎样 (if else的结构)
*干完了就怎样,干不完就别想怎样(while else 的结构)
循环顺利完成之后,才会执行else

def showMaxFactor(num):#求最大约数
    count = num // 2 #用向下取整除法
        while count > 1:
            if num % count == 0:
                print('%d最大公约数是%d' % (num, count))
                break #如果break出循环,是不会执行else的
            count -= 1
        else: #如果循环全部跑完,则执行else的内容
            print('%d是一个素数' % num)

*没问题就干吧 和异常处理搭配

try: #如果try内出错 则执行except语句块 否则执行else语句块
    int('abc')
except ValueError as reason:
    print('粗错了 T_T')
else:
    print('没有错')

22、with语句

try:
    with open('1.txt','w') as f:#系统会关注这个文件一旦没有使用 就会自动关闭
        for each_line in f:
            print(each_line)
except OSError as reason:

23、图形界面编程

http://easygui.sourceforge.net
easygui-docs=0.96\tutorial\index.html
bbs.fishc.com/thread-46069-1-1.html
导入库

>>> import easygui
>>> easygui.msgbox('hi lyy')
'OK'
>>> from easygui import *
>>> msgbox('see you again')
'OK'
>>> import easygui as g #推荐~
>>> g.msgbox('see you again again')
'OK'
>>> 
不要在IDLE上运行easygui,事件循环会和IDLE冲突
字体、窗口大小等,可以在源代码里修改
buttonbox添加图片只支持gif 在参数里写上 image="test.gif" 即可
multchoicebox 多选框
multernterbox 多输入框
EgStore 记住用户的设置

24、对象

代码段、函数、变量的封装
对象 = 属性 + 方法
类 class 类名大写字母开头
类的实例化 对象名 = 类名()
调用类的函数变量 对象名.函数名/对象名.变量名
静态属性:没有self.的属性,用类名.属性名 可以访问 ,可以用于计算类被实例化的次数
静态方法:在方法之前加上@staticmethod 不会绑定到实例对象上,节省开销
静态方法不需要self参数,因此即使用对象去访问,self参数也不能传递进去

OO的特征

封装

对外部隐藏工作细节

继承

继承之后 可以调用父类的所有函数和数据

class MyList(list)
    pass
list2 = MyList()#list2就拥有了list类的方法

多态

不同类的对象调用同一方法得到不同的结果

class A:
    def fun(self): #self相当于this指针
        print("A")
class B:
    def fun(self):
        print("B")
A.fun()
B.fun() #结果是不同的虽然名字相同

self

定义类的时候方法的第一个参数必须是self
调用的时候把调用者的信息给self
python的魔法方法

__init__(self) #相当于构造函数 可以定义类定义时的初始化操作
class Ball:
    #默认只有self 这里添加了name则初始化对象的时候 必须要传入一个name参数
    def __init__(self,name): #可以添加name默认值 防止忘记传参时报错
        self.name = name
    def kick(self):
        print(self.name)

私有公有

在变量名前面 加__双下划线 变成私有 本质上是通过修改变量名

class Person:
    __name = "A"
    def getName(self):
    return self.__name
p = Person()

p.name / p.__name都会报错
p.getName() / p._A_name都会成功得到 __name的值
Python的私有是伪私有!mangling

继承

class 子类名(父类名/超类名/基类名)
子类定义的同名方法会覆盖掉继承得到的父类的方法,只是覆盖 不是删除
如果不想要父类的某个方法,直接pass掉函数体就可以了
**super()函数
不需要明确给出基类的名字,他将会自动的找出所有基类以及对应的方法。
由于不用给出基类名,如果改变了继承关系,只要改变class语句里的父类即可,而不必大量去修改所有被继承的方法

import random as r
class Fish:
    def__init__(self):
    self.x = r.randint(0,10)
        self.y = r.randint(0,10)
    def move(self)
    self.x -= 1
        print("position :" ,self.x ,self.y)

class Goldfish(Fish)
    pass

class Carp(Fish)
    pass

class Salmon(Fish)
    pass

class Shark(Fish)
    def __init__(self):#重写了父类的__init__
       #Fish.__init__(self) # 调用未绑定的父类方法
       #super().__init__() #使用super函数
    self.hungry = True
    def eat(self):
    if self.hungry:
        print("Eat")
        self.hungry = False
    else:
        print("Full")

动态继承

如果要继承的基类是动态的(有时候是A有时候是B),则可以为基类定义一个别名。
在类定义的时候,用别名代替要继承的基类,如果要修改基类。只需要修改给别名赋值的那个语句即可

BaseAlias = BaseClass #为基类取别名
class Derived(BaseClass):
    def meth(self):
        BaseAlias.meth(self) #通过别名访问

多重继承

class 子类名(父类名1,父类名2…)
同时集成多个父类的方法

组合

把没什么关系的类放在一起

class Turtle
    def __init__(self,x):
        self.num = x
class Fish 
    def __init__(self,x):
        self.num = x
class pool:
    def __init__(self,x,y):
    self.tuetle = TurTle(x)
    self.fish = Fish(y)
    def print_num(self)
    print("There are %d turtles and %d fishes" % (self.turtle.num,self.fish.num))

把类的实例化放到一个新的类里面
组合用于”有一个”的场景
继承用于”是一个”的场景
*mix-in

类、类对象、实例对象

类属性和类对象是绑定的
对实例对象的变量赋值之后,则会覆盖掉原有类的变量
属性名跟方法名相同,则属性会覆盖方法。

绑定

要求方法要有实例才可以调用
类对象.方法()是会报错的,
要先将类实例化,用对象.方法()才可以调用方法

issubclass(class,classinfo)
一个类会被认为是自己的子类
自身可以认为是自身的子类
object是所有类的父类
isinstance(object,classinfo)
如果第一个参数不是对象 则永远是false
如果第二个参数不是类或者由类对象组成的元组 会抛出一个TypeError异常

hassttr(object,name) 测试指定对象是否有指定的属性
>>> class C:
    def __init__(self,x = 0):
    self.x = x
>>> c1 = C()
>>> hasattr(c1,'x')
True

getattr(object,name,[,default])
>>> getattr(c1,'x')
0
>>> getattr(c1,'y','您所访问的属性不存在') 
'您所访问的属性不存在'

setattr(object,name,value)
>>> setattr(c1,'y','yyy')

delattr(object,name)

property(fget=None,fset) 通过属性设置属性

>>> class C:
    def __init__(self,x = 0):
    self.x = x
    def getSize(self):
    return self.x
    def setSzie(self,value):
    self.x = value
    def delSize(self):
    del self.x
    y = property(getSize,setSize,delSize) #获取、设置、删除的方法
>>> c1 = C()
>>> c1.y #直接访问
>>> c1.y = 1 #直接赋值
>>> del c1.x #删掉对象

25、魔法方法

*运行过程中自动调用的一类函数
*被双下划线包围
*构造和析构:

__new__(cls[,...])

实例一个对象的时候第一个调用的方法
第一个参数不是self,而是cls,用来传递给__init__
当需要修改一个继承得到的不可变类的时候很重要(tuple,str)

class Capstr(str):#str是不可改变类 不能重写init
    def __nwe__(cls,string):
    string = string.upper() #只能重写new 
    return str.__new__(cls,string) #调用父类的new

__init__(self[,...])

构造方法 没有返回值
需要传入参数的时候 才需要从重写 init()
需要重新初始化的时候 才需要重写
不应当返回除None以外的任何东西

__del__(self)

析构方法
垃圾自动回收机制
del x != x.__del__()
del 操作不一定会调用__del__
只有所有的引用都被del 才会调用__del__

工厂函数:

其实就是一个类对象,当调用它们的时候事实上就是创建一个相应的实例对象
重写的魔法方法 会替代原有的魔法方法

当a对象的__add__没有实现或者不支持相应操作的时候,会调用b的__radd__方法

__getattr__(self,name) #定义当用户试图访问获取一个不存在的属性时的行为
__getattribute__(self,name) #定义当该类的属性被访问时的行为
__setattr__(self,name,value) #定义当一个属性被设置时的行为
__delattr__(self,name) #定义当一个属性被删除时的行为

name就是变量名

class C:
    def __getattribute__(self,name):
    print("getattribute")
    return super().__getattribute__(name)
    def __getattr__(self,name):
    print("getattr")
    def __setattr__(self,name,value):
    print("setattr")
    super().__setattr__(name,value)
    def __delattr__(self,name):
    print("delattr")
    super().__delattr__(name)

死循环陷阱

赋值的过程即setattr要调用基类的魔法方法

>>> super().__setattr__(name,value)

用dict方法解决

>>> self.__dict__[name] = value

__dict__给出类中除了魔法方法和某些特殊方法的所有的属性和方法

描述符

将某种特殊类型的类的实例指派给另一个类的属性
特殊类型:至少实现一个以下方法

__get__(self,instance,owner) #用于访问属性,返回属性的值
__set__(self,instance,value) #在属性分配操作中调用,不返回任何内容
__delete__(self,instance) #控制删除操作,不返回任何内容

访问实例层次上的描述符,只会返回描述符本身
为了让描述符正常工作,需要定义在类的层次上

#Temper.py:
class Celsius:#摄氏度类
    def __init__(self,value = 26.0):#初始化为26度
        self.value = float(value)
    def __get__(self,instance,owner):#当访问该类时,返回设置的温度
        return self.value
    def __set__(self,instance,value):#设置温度值
        self.value = float(value)

class Fahrenheit:
    def __get__(self,instance,owner):#获取该值的时候,进行如下计算把摄氏转为华氏
        return instance.cel * 1.8 + 32 #
    def __set__(self,instance,value):#设置该值的时候,进行如下计算转化成摄氏度
        instance.cel = (float(value) -32 )/ 1.8

class Temper:
    cel = Celsius()
    fah = Fahrenheit()

协议

类似于接口,更像是一种指南。
不会严格要求一定要怎么样去做,而是靠自觉和经验把事情做好
容器类型的协议
不可变(元组、字符串) 需要定义__len__()__getitem__()
可变 除了上述的两个还要定义 __setitem__()__delitem__()

__len__(self) #当被len()调用时的行为(返回容器中的元素个数)
__getitem__(self,key) #获取 self[key]的值
__setitem__(self,key,value) #设置self[key] = value
__delitem__(self,key) #删除指定元素 del self[key]
__iter__(self) #定义迭代容器中的元素的行为
__reversed__(self) #定义当被reversed()调用时的行为
__contains__(self,item) #定义当使用成员测试运算符(in 或者 not in)时的行为
class CountList:#不可变类型
    def __init__(self,*args):
        self.values = [x for x in args]
        self.count = ().fromkeys(range(len(self.values)),0)
    def __len__(self):
        return len(self.values)
    def __getitem__(self,values):
        self.count[key] += 1
        return self.values[key]

迭代器

序列、字典
iter() 得到迭代器
next() 逐个获取元素
set(集合)是不能用下标随机访问的数据结构,必须用迭代器访问

>>> string = "AAAAA"
>>> it = iter(string)
>>> next(it)
"A"
>>> next(it)
"A"
>>> while True:
    try:
        each = next(it)
    except StopIteration: #这个异常表示已经取空
        break
    print(each)

>>> for each in string:
    print(each)
>>> 

对应的魔法方法
__iter__() 返回迭代器 本身 return self
__next__()重点实现 如不加控制会没有终点

class Fibs:#定义斐波那契数列的序列自动计算类 初始化输入数列上界 top 默认为1--
    def __init__(self,top = 100):
    self.a = 0
    self.b = 1
    self.top = top
    def __iter__(self):
    return self
    def __next__(self):
    self.temp = self.a
    self.a = self.b
    self.b = self.temp + self.b
    if self.a > self.top:
        raise StopIteration
    return self.a

生成器

在普通的函数内增加 yield语句
协同程序 可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始
遇到yield就返回
协程的作用是生成值的序列
处理无穷序列

other = yield foo #表示返回foo的值,如果有值send过来,则将other设置为那个值
other = yield #也是合法的
def fibs()
    a = 0
    b = 1
    while True:
    a, b = b, a + b 
    yield a

for each in fibs(): 
    if each > 100:
    break
    print(each,end = ' ') 

列表推导式

a = [i for i in range(100) if not(i%2) and i%3]
得到100以内可以被2整除但不能被3整除的数

字典推导式

b = {i:i % 2 == 0 for i in range(100)}
构造字典,键为整数,值为他是否为偶数

集合推导式

c = {i for i in [1,1,2,3,4,5]}

字符串和元组是没有推导式的

但是元组会变成一个生成器推导式
sum(i for i in range(100) if i % 2)


26、爬虫

urllib
url格式: protocol://hostname[:port]/path/[;parameters][?query]#fragment
urlopen(url,[…])访问网页

import urllib.request
>>> res = urllib.request.urlopen("https://www.baidu.com")
>>> html = res.read()
>>> html=html.decode("utf-8")
>>> print(html)
<html>
    <head>  
        <script>        
            location.replace(location.href.replace("https://","http://"));  
        </script>
    </head>
    <body>          <noscript>
            <meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
        </noscript>
    </body>
</html>

userAgent 是模拟浏览器去访问网页 防止被阻挡
Form Data 提交的东西
修改header 增加参数修改 通过Request.add_header() 方法修改
防止被掐掉
①延迟发送时间 使用time模块
②使用代理
*设置字典 {‘类型’:’代理IP:端口’}
proxy_support = urllib.request.ProxyHandler({})
**定制、创建一个opener
opener = urllib.request.build_opener(proxy_support)
***a安装opener
urllib.request.install_opener(opener)#替换掉默认一劳永逸的办法
***b调用opener
opener.open(url)


27、正则表达式

re模块
.表示通配符 匹配除了换行符以外的字符
用\转义元字符
元字符如下
. ^ $ * + ? { } [ ] ( ) \ |
详解
[]
制定一个字符类用于存放需要匹配的字符集合
可以单独列出 [abc123]
也可以范围列出[0-9][a-z][A-Z]…
*元字符在[]内不会触发特殊效果
*[^5]表示匹配除5之外的所有字符

()
分组操作,将括号内的表达式看成一组,可以对其使用重复操作符
可以按层次索引,将索引值作为参数传递给查看结果的四大方法,序号0表示第一个分组,默认分组一直存在
有多少对括号就有多少个子组,从左到右编号,允许子组嵌套,从左到右统计”(“就可以确定子组的序号
可以调用group传入子组序号或序号列,得到匹配结果,可以调用groups显示全部子组
非捕获组,
(?:...) …可以换成任何正则表达式
防止分组过多,索引太复杂,不能从非捕获组获得匹配的内容
当需要修改一个现有模式的时候非常有用,因为添加一个非捕获组不会影响到其他的组的序号。
命名组,
(?P<name>...) …可以换成任何正则表达式
可以用有意义的名字代替序号来访问子组

\
转义符
特殊转普通 普通转特殊

符号说明
\d匹配任何十进制数 等价于 [0-9]
\D与\d相反,匹配任何非十进制数的字符 等价于[^0-9]
\s匹配任何空白字符(空格,换行,制表) 等价于[\t\r\n\f\v]
\S与\s相反
\w匹配任何单词字符 如果正则表达式以字节形式表示 等价于[a-zA-Z0-9_] 如果是一个字符串 则匹配所有unicode数据库中标记为字母的字符 可以用re.ASCII进一步限制其定义
\W与\w相反
\b匹配单词的开始或结束 “零宽断言”表示当前位置位于一个单词的边界,注意python中\b表示退格 要么转义要么原始字符串
\B与\b相反 表示非单词边界的位置,可以包含在一个字符类中[\s,.]匹配任何空白字符或 ‘,’或’.’
\加三个八进制数字或者第一个数字数0表示八进制数

.
匹配换行符以外的所有字符
如果设置了 re.DOTALL 则将匹配包括换行符的全部字符

*
指定前一个字符匹配零次或多次
默认是贪婪匹配 尽可能多的匹配字符串 直到正则表达式不匹配或者字符串结束

+
指定前一个字符匹配一次或多次

?
指定前一个字符匹配零次或一次
把某种东西标志位可选的 是?abc 可以匹配 “是abc” 也可以匹配 “abc”, “是” 是可选的

*? +? ??开启非贪婪匹配

{m,n} #m n 是十进制数 并且之间没有空格!
指定前一个字符必须匹配至少m次至多n次
{m,} 至少m次 至多无穷(20亿)
{,n} 至少0次 至多n次
{m} 重复m次

^
匹配字符串的开头

$
匹配字符串的结尾

|
或操作,优先级很低

\A
匹配字符串的开头,在没有设置MUTILINE之前 和 ^一样,但是设置之后 \A还是只会匹配开头

\Z
匹配字符串的结尾,道理和\A相似

编译正则表达式
re.compile(‘表达式’,参数) #参数就是一些对于默认值的修改 re.IGNORECASE
编译之后成为模式对象

编译标志
编译标志可以修改正则表达式的工作方式,可以用|链接多个标志表示同时设置 re.I|re.M

标志含义
ASCII,A使得转义符号\w,\b,\s,\d只能匹配ASCII字符
DOTALL,S使得通配符.匹配任何符号,包括换行符
IGNORECASE,I匹配的时候不区分大小写
LOCALE,L支持当前语言(区域)设置
MULTLINE,M多行匹配,影响^$ (设置以后,^不仅匹配开头还匹配行首,$还匹配行尾)
VERBOSE,X启用详细的正则表达式

(忽略掉表达式中没有转义的空格和#,使得可以添加注释和换行,和三引号字符串结合使用便于阅读)
使用全局方法还是先编译,取决于实际状况,
如果只是用一次通常选择模块级别的全局方法re.balabala(),
如果需要在循环中使用通常先编译再使用中模式级别的方法p.balabala()
为了避免过多的反斜杠\,使用原始字符串符号r非常必要

匹配目标正则字符串原始字符串
“\section”“\\section”r”\section”

实现匹配

方法功能
match()判断应正则表达式是否从开始处匹配一个字符串,匹配失败返回None 匹配成功返回一个包含所有匹配信息的对象
search()遍历字符串,找到正则表达式匹配的第一个位置,匹配失败返回None 匹配成功返回一个包含所有匹配信息的对象
findall()遍历字符串,找到正则表达式匹配的所有位置,并以列表返回
finditer()遍历字符串,找到正则表达式匹配的所有位置,并以迭代器返回
group()返回匹配的字符串,一次可以传入多个子组序号
start()返回匹配的开始位置
end()返回匹配的结束位置
span()返回一个元组表示匹配位置(start,end)

*如果返回的内容很多,则迭代器比列表要更好
如果正则表达式有子组 findall会将子组内容单独返回出来,如果有多个子组会组合成元组返回
实例:

>>> import re #导入模块
>>> p = re.compile(r'\d+') #编译表达式
>>> p.search(r"a1bb22ccc333dddd4444") #调用search匹配
<_sre.SRE_Match object; span=(1, 2), match='1'>
>>> p.findall(r"a1bb22ccc333dddd4444")#列表返回结果
['1', '22', '333', '4444']
>>> iterator = p.finditer(r"a1bb22ccc333dddd4444") #迭代器返回结果
>>> for match in iterator:
    print(str(match.span())+"\t"+str(match.group()))


(1, 2)  1
(4, 6)  22
(9, 12) 333
(16, 20)    4444
>>> 

反向引用
(...)\1表示后接一个子组1的内容作为表达式的一部分再次引用
(...)(?P=name)表示name指向的组需要在当前位置再次引用

前向断言
也是一种零宽断言,分为前向肯定断言和前向否定断言
肯定(?=...)如果当前包含的正则表达式在当前位置匹配成功则代表成功,一旦该部分正则表达式被匹配引擎尝试过,就不会再继续匹配了,剩下的部模式再次断言开始的地方继续尝试
否定(?!...)与肯定断言相反
实例:
想要匹配除了bat和exe以外的所有文件
.*[.](?!bat$|exe$).*$
解释:
[.]表示文件名和后缀名之间的.
之前的.*表示间隔符前面有任意长的字符串
(?!bat$|exe$)表示如果间隔符之后的字符串是bat或exe则匹配失败,$是为了防止误杀batch之类的包含了敏感信息的字符串
.*$表示间隔符之后到整个字符串结束有任意长的字符串

修改字符串

方法用途
split()在正则表达式匹配的地方进行分割,并返回一个列表
sub()找到所有匹配的子字符串,并替换为新的内容
subn()跟sub的作用相同,单返回新的字符串以及替换的数目

分割字符串
re.split(r"表达式","待匹配串",分割片数)
[如果片数是2,表示至多有2个分割会被处理,剩下的放在最后一个元素]
如果要查看分隔符,只需将表达式设置成捕获组
搜索和替换字符串
找到所有匹配的部分并替换成不同的字符串就可以用sub
sub(replacement,string[,count=0])
返回一个字符串,从最左边开始所有匹配的地方都换成replacement的内容,如果没有匹配到则返回原字符串
count表示最多替换的次数,必须是一个非负数,默认0表示替换全部匹配位置
subn与sub类似,但是返回值为一个元组(替换后的字符串,替换数目)
空匹配只有他们没有紧挨着前一个匹配时才会被替换掉

>>> p = re.compile('x*')
>>> q = re.compile('x+')
>>> p.sub('-','abxd')
'-a-b-d-'
>>> q.sub('-','abxd')
'ab-d'

如果replacement参数是一个字符串,那么里面的反斜杠都会被处理,\r\n\t\f\v转化为相应空格
未知转义如\j保持原样,
逆向引用如\6会被相应的捕获组匹配的内容所替换使得可以在替换后的字符串中插入一部分原字符串的内容
在sub中可以使用\g<name> \g<数字> 引用命名组
还可以将sub的第一个参数换成一个函数,当匹配成功时,取得内ring并用函数计算出新的字符串返回

当试图匹配XML HTML时 正则表达式不一定是最好选择,可以用对应的解释器来解析匹配

符号总结表

字符含义
.表示匹配除了换行符外的任何字符
注:通过设置 re.DOTALL 标志可以使 . 匹配任何字符(包含换行符)
|A | B,表示匹配正则表达式 A 或者 B
^ (脱字符)匹配输入字符串的开始位置
如果设置了 re.MULTILINE 标志,^ 也匹配换行符之后的位置
$ 匹配输入字符串的结束位置
如果设置了 re.MULTILINE 标志,$ 也匹配换行符之前的位置
\ 将一个普通字符变成特殊字符,例如 \d 表示匹配所有十进制数字
解除元字符的特殊功能,例如 . 表示匹配点号本身
引用序号对应的子组所匹配的字符串
详见下方列举
[…]字符类,匹配所包含的任意一个字符
注1:连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位则仅作为普通字符
注2:特殊字符仅有反斜线 \ 保持特殊含义,用于转义字符。其它特殊字符如 *、+、? 等均作为普通字符匹配
注3:脱字符 ^ 如果出现在首位则表示匹配不包含其中的任意字符;
如果 ^ 出现在字符串中间就仅作为普通字符匹配
{M,N}M 和 N 均为非负整数,其中 M <= N,表示前边的 RE 匹配 M ~ N 次
注1:{M,} 表示至少匹配 M 次
注2:{,N} 等价于 {0,N}
注3:{N} 表示需要匹配 N 次
*匹配前面的子表达式零次或多次,等价于 {0,}
+匹配前面的子表达式一次或多次,等价于 {1,}
?匹配前面的子表达式零次或一次,等价于 {0,1}
*?, +?, ??默认情况下 *、+ 和 ? 的匹配模式是贪婪模式(即会尽可能多地匹配符合规则的字符串);
*?、+? 和 ?? 表示启用对应的非贪婪模式。
举个栗子:对于字符串 “FishCCC”,正则表达式 FishC+ 会匹配整个字符串,而 FishC+? 则匹配 “FishC”。
{M,N}?同上,启用非贪婪模式,即只匹配 M 次(…)匹配圆括号中的正则表达式,或者指定一个子组的开始和结束位置
注:子组的内容可以在匹配之后被 \数字 再次引用
(\w+) \1可以字符串 “FishC FishC.com”中的 “FishC FishC”(注意有空格)
(?…)(? 开头的表示为正则表达式的扩展语法(下边这些是 Python 支持的所有扩展语法)
(?aiLmsux) (? 后可以紧跟着 ‘a’,’i’,’L’,’m’,’s’,’u’,’x’ 中的一个或多个字符,
只能在正则表达式的开头使用
每一个字符对应一种匹配标志:
re-A(只匹配 ASCII 字符),
re-I(忽略大小写),
re-L(区域设置),
re-M(多行模式),
re-S(. 匹配任何符号),
re-X(详细表达式),包含这些字符将会影响整个正则表达式的规则
当你不想通过 re.compile() 设置正则表达式标志,这种方法就非常有用
注意,由于 (?x) 决定正则表达式如何被解析,所以它应该总是被放在最前边(最多允许前边有空白符)。
如果 (?x) 的前边是非空白字符,那么 (?x) 就发挥不了作用了。
(?:…)非捕获组,即该子组匹配的字符串无法从后边获取
(?P<name>...)命名组,通过组的名字(name)即可访问到子组匹配的字符串(?P=name)反向引用一个命名组,它匹配指定命名组匹配的任何内容
(?#…)注释,括号中的内容将被忽略
(?=…)前向肯定断言。如果当前包含的正则表达式(这里以 … 表示)在当前位置成功匹配,则代表成功,否则失败。
一旦该部分正则表达式被匹配引擎尝试过,就不会继续进行匹配了;剩下的模式在此断言开始的地方继续尝试。
举个栗子:love(?=FishC) 只匹配后边紧跟着 “FishC”的字符串 “love”
(?!…)前向否定断言。这跟前向肯定断言相反(不匹配则表示成功,匹配表示失败)。
举个栗子:FishC(?!.com) 只匹配后边不是 “.com”的字符串 “FishC”
(?<=…)后向肯定断言。跟前向肯定断言一样,只是方向相反。
举个栗子:(?<=love)FishC 只匹配前边紧跟着 “love”的字符串 “FishC”
(?后向否定断言。跟前向肯定断言一样,只是方向相反。
举个栗子:(?
(?(id/name)yes-pattern|no-pattern)如果子组的序号或名字存在的话,则尝试 yes-pattern 匹配模式;否则尝试 no-pattern 匹配模式
no-pattern 是可选的
举个栗子:`(<)?(\w+@\w+(?:.\w+)+)(?(1)>
可以匹配<user@fishc.com> 和 'user@fishc.com'
但是不会匹配 <user@fishc.comuser@fishc.com>
\下边列举了由字符 ‘\’ 和另一个字符组成的特殊含义。
注意,’\’ + 元字符的组合可以解除元字符的特殊功能
\序号 引用序号对应的子组所匹配的字符串,子组的序号从 1 开始计算
如果序号是以 0 开头,或者 3 个数字的长度。那么不会被用于引用对应的子组,而是用于匹配八进制数字所表示的 ASCII 码值对应的字符
举个栗子:(.+) \1 会匹配 “FishC FishC” 或 “55 55”,但不会匹配 “FishCFishC”
(注意,因为子组后边还有一个空格)
\A匹配输入字符串的开始位置
\Z匹配输入字符串的结束位置
\b匹配一个单词边界,单词被定义为 Unidcode 的字母数字或下横线字符() ” ” !都是边界
举个栗子:\bFishC\b 会匹配字符串 “love FishC”、FishC.” 或”FishC)”
\B匹配非单词边界,其实就是与 \b 相反
举个栗子:py\B 会匹配字符串 “python”、”py3” 或 “py2”,但不会匹配 “py “、”py.” 或 “py!”
\d 对于 Unicode(str 类型)模式:匹配任何一个数字,包括 [0-9] 和其他数字字符;
如果开启了 re.ASCII 标志,就只匹配 [0-9]
对于 8 位(bytes 类型)模式:匹配 [0-9] 中任何一个数字
\D匹配任何非 Unicode 的数字,其实就是与 \d 相反;
如果开启了 re.ASCII 标志,则相当于匹配 [^0-9]
\s 对于 Unicode(str 类型)模式:匹配 Unicode 中的空白字符(包括 [ \t\n\r\f\v] 以及其他空白字符);
如果开启了 re.ASCII 标志,就只匹配 [ \t\n\r\f\v]
对于 8 位(bytes 类型)模式:匹配 ASCII 中定义的空白字符,即 [ \t\n\r\f\v]
\S匹配任何非 Unicode 中的空白字符,其实就是与 \s 相反;
如果开启了 re.ASCII 标志,则相当于匹配 [^ \t\n\r\f\v]
\w 对于 Unicode(str 类型)模式:匹配任何 Unicode 的单词字符,
基本上所有语言的字符都可以匹配,当然也包括数字和下横线;
如果开启了 re.ASCII 标志,就只匹配 [a-zA-Z0-9_]
对于 8 位(bytes 类型)模式:匹配 ASCII 中定义的字母数字,即 [a-zA-Z0-9_]
\W匹配任何非 Unicode 的单词字符,其实就是与 \w 相反;
如果开启了 re.ASCII 标志,则相当于 [^a-zA-Z0-9_]
转义符号正则表达式还支持大部分 Python 字符串的转义符号:\a,\b,\f,\n,\r,\t,\u,\U,\v,\x,\
注1:\b 通常用于匹配一个单词边界,只有在字符类中才表示“退格”
注2:\u 和 \U 只有在 Unicode 模式下才会被识别
注3:八进制转义(\数字)是有限制的,
如果第一个数字是 0,或者如果有 3 个八进制数字,那么就被认为是八进制数;
其他情况则被认为是子组引用;
至于字符串,八进制转义总是最多只能是 3 个数字的长度

28、访问网页的异常处理

URLError异常 reason包含了错误编码和错误信息的元组
HTTPError是URLError的子类

import urllib.request
import urllib.error #错误包含在error模块中

req = urllib.request.Requset("http://www.fishc.com")
try:
    urllib.request.urlopen(req)
except urllib.error.HTTPError as e: #这个要写在前面
    print(e.code) #返回状态码
    print(e.read()) #打印出错误的页面
except url.error.URLError as ee: #写在后面
    print(ee.reason) #打印错误信息
#推荐第二种写法:
try:
    urllib.request.urlopen(req)
except URLError as e:
    if hasattr(e,'reason'):
        print("Reason: ",e.reason)
    elif hasattr(e,'code'):
        print("ErrorCode: ",e.code)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值