文章目录
1 file文件
a. open打开
Python open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。
注意:使用 open() 方法一定要保证关闭文件对象,即调用 close() 方法。
open() 函数常用形式是接收两个参数:文件名(file)和模式(mode)。
open(file, mode='r')
完整语法:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明:
- file: 必需,文件路径(相对或者绝对路径)。
- mode: 可选,文件打开模式
- buffering: 设置缓冲
- encoding: 一般使用utf8
- errors: 报错级别
- newline: 区分换行符
- closefd: 传入的file参数类型
- opener:
mode 参数有:
默认为文本模式,如果要以二进制模式打开,加上 b
b. file 对象
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:
c. csv文件和excel文件
CSV(Comma-Separated Values)即逗号分隔值,可以用Excel打开查看。由于是纯文本,任何编辑器也都可打开。与 Excel 文件不同,CSV 文件中:
- 值没有类型,所有值都是字符串
- 不能指定字体颜色等样式
- 不能指定单元格的宽高,不能合并单元格
- 没有多个工作表
- 不能嵌入图像图表
i. csv数据读取
在CSV文件中,以 , 作为分隔符,分隔两个单元格。
不是每个逗号都表示单元格之间的分界。所以即使CSV是纯文本文件,也坚持使用专门的模块进行处理。Python内置了csv模块。先看看一个简单的例子。
# -*- coding:utf-8 -*-
import csv
filename = "airports.csv"
with open(filename) as f:
reader = csv.reader(f)
print(list(reader))
部分结果:
'450', 'NA', 'US', 'US-TX', 'Franklin', 'no', '', '', '', '', '', '09TA'], ['322207', 'US-0426', 'small_airport', 'XWind Farm Airport', '33.724417', '-96.298306', '512', 'NA', 'US', 'US-TX', 'Ravenna', 'no', '09TA', '', '09TA', '', '', 'https://web.archive.org/web/20150925002817/http://www.airnav.com/airport/09TA'], ['322208', 'US-0427', 'small_airport', 'Evan Airport', '30.314672', '-90.907972', '17', 'NA', 'US', 'US-LA', 'Prairieville', 'no', '', '', '', '', '', ''], ['322211', 'US-0428', 'small_airport', 'Sanctuary Ranch Airport', '32.056457', '-96.045951', '264', 'NA', 'US', 'US-TX', 'Crossroads', 'no', '7TS4', '', '7TS4', '', '', ''], ['322212', 'US-0429', 'small_airport', 'Linn County Airport', '38.173431', '-94.690325', '860', 'NA', 'US', 'US-KS', 'Pleasanton', 'no', '', '', '1KS', '', '', ''], ['322221', 'US-0430', 'heliport', 'J&J New Brunswick Helistop', '40.501837', '-74.445735', '23', 'NA', 'US', 'US-NJ', 'New Brunswick', 'no', '06NJ', '', '06NJ', '', '', ''], ['322222', 'US-0431', 'heliport', "St. Mary's Good Samaritan Heliport", '38.297222', '-88.937778', '501', 'NA', 'US', 'US-IA', 'Mt. Vernon', 'no', '4IL6', '', '4IL6', '', '', ''], ['322226', 'US-0432', 'heliport', 'Honeywell Heliport', '40.837083', '-74.476694', '201', 'NA', 'US', 'US-NJ', 'Morris Plains', 'no', '12NJ', '', '12NJ', '', '', 'Johnson & Johnson Heliport'], ['322231', 'US-0433', 'small_airport', 'Barren Creek Field Airport', '38.455384', '-75.797167', '21', 'NA', 'US', 'US-MD', 'Mardela Springs', 'no', 'MD80', '', 'MD80', '', '', '55MD'], ['322238', 'US-0434', 'heliport', 'UCSD Health System East Campus Interim Heliport', '32.876406', '-117.2210194', '335', 'NA', 'US', 'US-CA', 'La Jolla', 'no', '52CA', '', '52CA', '', '', ''], ['322245', 'US-0435', 'small_airport', 'Windsor Farms Airport', '35.227514', '-78.817261', '180', 'NA', 'US', 'US-NC', 'Linden', 'no', '4NC3', '', '4NC3', '', '', ''], ['322247', 'US-0436', 'small_airport', "Sohler's Holly Hill Airport", '45.413389', '-122.993917', '277', 'NA', 'US', 'US-OR', 'Hillsboro', 'no', 'OR31', '', 'OR31', '', '', ''], ['322261', 'US-0437', 'heliport', 'The Medical Center at Franklin Heliport', '36.700043', '-86.577725', '723', 'NA', 'US', 'US-KY', 'Franklin', 'no', '81KY', '', '81KY', '', '', ''], ['322275', 'US-0438', 'heliport', 'Benson Heliport', '45.314167', '-95.613889', '1033', 'NA', 'US', 'US-MN', 'Benson', 'no', 'MN84', '', 'MN84', '', '', ''], ['322278', 'US-0439', 'small_airport', 'Hallick Farm Airport', '43.099444', '-89.776389', '1097', 'NA', 'US',
ii. 写入csv
import csv
headers = ['class','name','gender','height','year']
rows = [
[1,'xiaoming','male',168,23],
[1,'xiaohong','female',162,22],
[2,'xiaozhang','female',163,21],
[2,'xiaoli','male',158,21]
]
with open('test.csv','w')as f:
f_csv = csv.writer(f)
f_csv.writerow(headers)
f_csv.writerows(rows)
iii. error 2
FileNotFoundError: [Errno 2] No such file or directory
无法找到路径,python会在默认文件夹中寻找,如果没有,需要先确定current work directory
os.getcwd()
os模块
Python OS 文件/目录方法
os 模块提供了非常丰富的方法用来处理文件和目录,内置了很多库,
| 序号 | 方法描述 |
|---|---|
| 1 |
os.access(path, mode)检验权限模式 |
| 2 |
os.chdir(path) 改变当前工作目录 |
完整列表请参考python OS模块
datetime 模块
datetime模块提供了简单和复杂的方式用于操纵日期和时间的类。虽然支持日期和时间运算,但实现的重点是为了输出格式化和操作高效地提取属性。
模块内容
| 内容 | 描述 |
|---|---|
| 常量 | |
| datetime.MINYEAR | date和datetime对象允许的最小年份 |
| datetime.MAXYEAR | date和datetime对象允许的最大年份 |
| 类 | |
| datetime.date | 日期对象,属性(year, month, day) |
| datetime.time | 时间对象,属性(hour, minute, second, microsecond, tzinfo) |
| datetime.datetime | 日期时间对象,属性(date和time属性组合) |
| datetime.timedelta | Difference between two datetime values |
| datetime.tzinfo | 时区信息对象的抽象基类, datetime和time类使用它定制化时间调节 |
datetime 类
datetime是Python处理日期和时间的标准库。
date对象表示理想化日历中的日期(年、月和日), 公历1年1月1日被称为第一天,依次往后推。
获取当前日期和时间
from datetime import datetime
now = datetime.now()
print (now)
Result
2019-04-09 13:31:35.474343
Process finished with exit code 0
注意到datetime是模块,datetime模块还包含一个datetime类,通过from datetime import datetime导入的才是datetime这个类。
如果仅导入import datetime,则必须引用全名datetime.datetime。
datetime.now()返回当前日期和时间,其类型是datetime。
获取指定日期和时间
要指定某个日期和时间,我们直接用参数构造一个datetime:
>>> from datetime import datetime
>>> dt = datetime(2015, 4, 19, 12, 20) # 用指定日期时间创建datetime
>>> print(dt)
2015-04-19 12:20:00
timestamp 转换为datetime
要把timestamp转换为datetime,使用datetime提供的fromtimestamp()方法:
>>> from datetime import datetime
>>> t = 1429417200.0
>>> print(datetime.fromtimestamp(t))
2015-04-19 12:20:00
str转化为datetime
很多时候,用户输入的日期和时间是字符串,要处理日期和时间,首先必须把str转换为datetime。转换方法是通过datetime.strptime()实现,需要一个日期和时间的格式化字符串:
>>> from datetime import datetime
>>> cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
>>> print(cday)
2015-06-01 18:19:59
字符串’%Y-%m-%d %H:%M:%S’规定了日期和时间部分的格式。详细的说明请参考python官方文档。
datetime转换为str
datetime转换为str
如果已经有了datetime对象,要把它格式化为字符串显示给用户,就需要转换为str,转换方法是通过strftime()实现的,同样需要一个日期和时间的格式化字符串:
>>> from datetime import datetime
>>> now = datetime.now()
>>> print(now.strftime('%a, %b %d %H:%M'))
Mon, May 05 16:28
datetime 加减
对日期和时间进行加减实际上就是把datetime往后或往前计算,得到新的datetime。加减可以直接用+和-运算符,不过需要导入timedelta这个类:
>>> from datetime import datetime, timedelta
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 16, 57, 3, 540997)
>>> now + timedelta(hours=10)
datetime.datetime(2015, 5, 19, 2, 57, 3, 540997)
>>> now - timedelta(days=1)
datetime.datetime(2015, 5, 17, 16, 57, 3, 540997)
>>> now + timedelta(days=2, hours=12)
datetime.datetime(2015, 5, 21, 4, 57, 3, 540997)
使用timedelta可以计算出前几天和后几天的时刻。
4. 类和对象
I. 面向对象
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法:类中定义的函数。
- 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
- 局部变量:定义在方法中的变量,只作用于当前实例的类。
- 实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
- 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 实例化:创建一个类的实例,类的具体对象。
- 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
和其它编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。
对象可以包含任意数量和类型的数据。
ii. 类定义
class ClassName:
<statement-1>
.
.
.
<statement-N>
类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。
类对象
类对象支持两种操作:属性引用和实例化。
属性引用使用和 Python 中所有的属性引用一样的标准语法:obj.name。
类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样:
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
以上创建了一个新的类实例并将该对象赋给局部变量 x,x 为空的对象。
执行以上程序输出结果为:
Result:
MyClass 类的属性 i 为: 12345
MyClass 类的方法 f 输出为: hello world
类有一个名为 init() 的特殊方法(构造方法),该方法在类实例化时会自动调用,像下面这样:
def __init__(self):
self.data = []
类定义了 init() 方法,类的实例化操作会自动调用 init() 方法。如下实例化类 MyClass,对应的 init() 方法就会被调用:
x = MyClass()
当然, init() 方法可以有参数,参数通过 init() 传递到类的实例化操作上。例如:
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
self代表类的实例,而非类
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
以上实例执行结果为:
<__main__.Test instance at 0x100771878>
__main__.Test
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。
self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:
class Test:
def prt(runoob):
print(runoob)
print(runoob.__class__)
t = Test()
t.prt()
Result
<__main__.Test instance at 0x100771878>
__main__.Test
类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('Iron Man',10,30)
p.speak()
Result:
Iron Man 说: 我 50 岁。
Process finished with exit code 0
i. 类属性和方法
类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。
self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定是用 self。
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。
实例
类的私有属性实例如下:
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量
Result
报错,实例不能访问私有变量
1
2
2
Traceback (most recent call last):
File "test.py", line 16, in <module>
print (counter.__secretCount)
AttributeError: 'JustCounter' object has no attribute '__secretCount'
iii.类的专用方法
- init : 构造函数,在生成对象时调用
- del : 析构函数,释放对象时使用
- repr : 打印,转换
- setitem : 按照索引赋值
- getitem: 按照索引获取值
- len: 获得长度
- cmp: 比较运算
- call: 函数调用
- add: 加运算
- sub: 减运算
- mul: 乘运算
- truediv: 除运算
- mod: 求余运算
- pow: 乘方
5. 正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
这个模块提供了与 Perl 语言类似的正则表达式匹配操作。
要搜索的样式和字符串可以是 Unicode 字符串 (str) 以及8位字节串 (bytes)。 但是,Unicode 字符串与8位字节串不能混用:也就是说,你不能用一个字节串样式去匹配 Unicode 字符串,反之亦然;类似地,当进行替换操作时,替换字符串必须与所用的样式和搜索字符串都为相同类型。
正则表达式使用反斜框字符 (’’) 来提示特殊形式或是允许使用特殊字符而又不启用它们的特殊含义。 这会与 Python 在字符串字面值中出于相同目的而使用的相同字符发生冲突;例如,为了匹配一个反斜杠字面值,样式字符串就需要写成 ‘\\’,因为正则表达式必须写成 \,而每个反斜杠在普通的 Python 字符串字面值内又必须写成 \。
解决办法是对于正则表达式样式使用 Python 的原始字符串表示法;在带有 ‘r’ 前缀的字符串字面值中,反斜杠不必做任何特殊处理。 因此 r"\n" 表示包含 ‘’ 和 ‘n’ 两个字符的字符串,而 “\n” 则表示只包含一个换行符的字符串。 样式在 Python 代码中通常都会使用这种原始字符串表示法来表示。
绝大部分正则表达式操作都提供为模块函数和方法,在 编译正则表达式. 这些函数是一个捷径,不需要先编译一个正则对象,但是损失了一些优化参数。
i. 正则表达式语法
一个正则表达式(或RE)指定了一集与之匹配的字符串;模块内的函数可以让你检查某个字符串是否跟给定的正则表达式匹配(或者一个正则表达式是否匹配到一个字符串,这两种说法含义相同)。
正则表达式可以拼接; 如果 A 和 B 都是正则表达式, 那么 AB 也是正则表达式。 通常, 如果字符串 p 匹配 A 并且另一个字符串 q 匹配 B, 那么 pq 可以匹配 AB。除非 A 或者 B 包含低优先级操作,A 和 B 存在边界条件;或者命名组引用。所以,复杂表达式可以很容易的从这里描述的简单源语表达式构建。 了解更多正则表达式理论和实现,参考the Friedl book [Frie09] ,或者其他编译器构建的书籍。
以下是正则表达式格式的简要说明。更详细的信息和演示,参考 正则表达式HOWTO。
正则表达式可以包含普通或者特殊字符。绝大部分普通字符,比如 ‘A’, ‘a’, 或者 ‘0’,都是最简单的正则表达式。它们就匹配自身。你可以拼接普通字符,所以 last 匹配字符串 ‘last’. (在这一节的其他部分,我们将用 this special style 这种方式表示正则表达式,通常不带引号,要匹配的字符串用 ‘in single quotes’ ,单引号形式。)
有些字符,比如 ‘|’ 或者 ‘(’,属于特殊字符。 特殊字符既可以表示它的普通含义, 也可以影响它旁边的正则表达式的解释。
重复修饰符 (, +, ?, {m,n}, 等) 不能直接嵌套。这样避免了非贪婪后缀 ? 修饰符,和其他实现中的修饰符产生的多义性。要应用一个内层重复嵌套,可以使用括号。 比如,表达式 (?:a{6}) 匹配6个 ‘a’ 字符重复任意次数。
特殊字符是:
.
(点) 在默认模式,匹配除了换行的任意字符。如果指定了标签 DOTALL ,它将匹配包括换行符的任意字符。
^
(插入符号) 匹配字符串的开头, 并且在 MULTILINE 模式也匹配换行后的首个符号。
$
匹配字符串尾或者换行符的前一个字符,在 MULTILINE 模式匹配换行符的前一个字符。 foo 匹配 ‘foo’ 和 ‘foobar’ , 但正则 foo$ 只匹配 ‘foo’。更有趣的是, 在 ‘foo1\nfoo2\n’ 搜索 foo.$ ,通常匹配 ‘foo2’ ,但在 MULTILINE 模式 ,可以匹配到 ‘foo1’ ;在 ‘foo\n’ 搜索 $ 会找到两个空串:一个在换行前,一个在字符串最后。
*
对它前面的正则式匹配0到任意次重复, 尽量多的匹配字符串。 ab* 会匹配 ‘a’, ‘ab’, 或者 ‘a’后面跟随任意个‘b’。
+
对它前面的正则式匹配1到任意次重复。 ab+ 会匹配 ‘a’ 后面跟随1个以上到任意个 ‘b’,它不会匹配 ‘a’。
?
对它前面的正则式匹配0到1次重复。 ab? 会匹配 ‘a’ 或者 ‘ab’。
?, +?, ??
'’, ‘+’,和 ‘?’ 修饰符都是 贪婪的;它们在字符串进行尽可能多的匹配。有时候并不需要这种行为。如果正则式 <.> 希望找到 ’ b ',它将会匹配整个字符串,而不仅是 ‘’。在修饰符之后添加 ? 将使样式以 非贪婪方式或者 :dfn:最小 方式进行匹配; 尽量 少 的字符将会被匹配。 使用正则式 <.?> 将会仅仅匹配 ‘’。
“{m}”
对其之前的正则式指定匹配 m 个重复;少于 m 的话就会导致匹配失败。比如, a{6} 将匹配6个 ‘a’ , 但是不能是5个。
“{m, n}”
对正则式进行 m 到 n 次匹配,在 m 和 n 之间取尽量多。 比如,a{3,5} 将匹配 3 到 5个 ‘a’。忽略 m 意为指定下界为0,忽略 n 指定上界为无限次。 比如 a{4,}b 将匹配 ‘aaaab’ 或者1000个 ‘a’ 尾随一个 ‘b’,但不能匹配 ‘aaab’。逗号不能省略,否则无法辨别修饰符应该忽略哪个边界。
{m,n}?
前一个修饰符的非贪婪模式,只匹配尽量少的字符次数。比如,对于 ‘aaaaaa’, a{3,5} 匹配 5个 ‘a’ ,而 a{3,5}? 只匹配3个 ‘a’。
转义特殊字符(允许你匹配 ‘*’, ‘?’, 或者此类其他),或者表示一个特殊序列;特殊序列之后进行讨论。
如果你没有使用原始字符串( r’raw’ )来表达样式,要牢记Python也使用反斜杠作为转义序列;如果转义序列不被Python的分析器识别,反斜杠和字符才能出现在字符串中。如果Python可以识别这个序列,那么反斜杠就应该重复两次。这将导致理解障碍,所以高度推荐,就算是最简单的表达式,也要使用原始字符串。
[]
用于表示一个字符集合。在一个集合中:
字符可以单独列出,比如 [amk] 匹配 ‘a’, ‘m’, 或者 ‘k’。
可以表示字符范围,通过用 ‘-’ 将两个字符连起来。比如 [a-z] 将匹配任何小写ASCII字符, [0-5][0-9] 将匹配从 00 到 59 的两位数字, [0-9A-Fa-f] 将匹配任何十六进制数位。 如果 - 进行了转义 (比如 [a-z])或者它的位置在首位或者末尾(如 [-a] 或 [a-]),它就只表示普通字符 ‘-’。
特殊字符在集合中,失去它的特殊含义。比如 [(+)] 只会匹配这几个文法字符 ‘(’, ‘+’, '’, or ‘)’。
字符类如 \w 或者 \S (如下定义) 在集合内可以接受,它们可以匹配的字符由 ASCII 或者 LOCALE 模式决定。
不在集合范围内的字符可以通过 取反 来进行匹配。如果集合首字符是 ‘^’ ,所有 不 在集合内的字符将会被匹配,比如 [^5] 将匹配所有字符,除了 ‘5’, [^^] 将匹配所有字符,除了 ‘^’. ^ 如果不在集合首位,就没有特殊含义。
在集合内要匹配一个字符 ‘]’,有两种方法,要么就在它之前加上反斜杠,要么就把它放到集合首位。比如, [()[]{}] 和 [{}] 都可以匹配括号。
Unicode Technical Standard #18 里的嵌套集合和集合操作支持可能在未来添加。这将会改变语法,所以为了帮助这个改变,一个 FutureWarning 将会在有多义的情况里被 raise,包含以下几种情况,集合由 ‘[’ 开始,或者包含下列字符序列 ‘–’, ‘&&’, ‘~~’, 和 ‘||’。为了避免警告,需要将它们用反斜杠转义。
在 3.7 版更改: 如果一个字符串构建的语义在未来会改变的话,一个 FutureWarning 会 raise 。
|
A|B, A 和 B 可以是任意正则表达式,创建一个正则表达式,匹配 A 或者 B. 任意个正则表达式可以用 ‘|’ 连接。它也可以在组合(见下列)内使用。扫描目标字符串时, ‘|’ 分隔开的正则样式从左到右进行匹配。当一个样式完全匹配时,这个分支就被接受。意思就是,一旦 A 匹配成功, B 就不再进行匹配,即便它能产生一个更好的匹配。或者说,’|’ 操作符绝不贪婪。 如果要匹配 ‘|’ 字符,使用 |, 或者把它包含在字符集里,比如 [|].
(…)
(组合),匹配括号内的任意正则表达式,并标识出组合的开始和结尾。匹配完成后,组合的内容可以被获取,并可以在之后用 \number 转义序列进行再次匹配,之后进行详细说明。要匹配字符 ‘(’ 或者 ‘)’, 用 ( 或 ), 或者把它们包含在字符集合里: [(], [)].
(?…)
这是个扩展标记法 (一个 ‘?’ 跟随 ‘(’ 并无含义)。 ‘?’ 后面的第一个字符决定了这个构建采用什么样的语法。这种扩展通常并不创建新的组合; (?P…) 是唯一的例外。 以下是目前支持的扩展。
(?aiLmsux)
( ‘a’, ‘i’, ‘L’, ‘m’, ‘s’, ‘u’, ‘x’ 中的一个或多个) 这个组合匹配一个空字符串;这些字符对正则表达式设置以下标记 re.A (只匹配ASCII字符), re.I (忽略大小写), re.L (语言依赖), re.M (多行模式), re.S (点dot匹配全部字符), re.U (Unicode匹配), and re.X (冗长模式)。 (这些标记在 模块内容 中描述) 如果你想将这些标记包含在正则表达式中,这个方法就很有用,免去了在 re.compile() 中传递 flag 参数。标记应该在表达式字符串首位表示。
(?:…)
正则括号的非捕获版本。只识别,不取值。匹配在括号内的任何正则式,但匹配完成后,这个子串不做为结果被获取。比如 (?:a)bc 指定了匹配样式 bc,但这个样式前面必须是字符 a,它可以匹配 ‘abc’,但不能匹配 ‘bbc’,匹配完成后只返回 ‘bc’ 作为匹配内容。
(?aiLmsux-imsx:…)
(‘a’, ‘i’, ‘L’, ‘m’, ‘s’, ‘u’, ‘x’ 中的0或者多个, 之后可选跟随 ‘-’ 在后面跟随 ‘i’ , ‘m’ , ‘s’ , ‘x’ 中的一到多个 .) 这些字符为表达式的其中一部分 设置 或者 去除 相应标记 re.A (只匹配ASCII), re.I (忽略大小写), re.L (语言依赖), re.M (多行), re.S (点匹配所有字符), re.U (Unicode匹配), and re.X (冗长模式)。(标记描述在 模块内容 .)
‘a’, ‘L’ and ‘u’ 作为内联标记是相互排斥的, 所以它们不能结合在一起,或者跟随 ‘-’ 。 当他们中的某个出现在内联组中,它就覆盖了括号组内的匹配模式。在Unicode样式中, (?a:…) 切换为 只匹配ASCII, (?u:…) 切换为Unicode匹配 (默认). 在byte样式中 (?L:…) 切换为语言依赖模式, (?a:…) 切换为 只匹配ASCII (默认)。这种方式只覆盖组合内匹配,括号外的匹配模式不受影响。
6. re模块
re 模块提供了 re.compile() 函数将一个字符串编译成 pattern object,用于匹配或搜索。函数原型如下:
i. 编译正则表达式
re.compile(pattern, flags=0)
re.compile() 还接受一个可选的参数 flag,用于指定正则匹配的模式。
p = re.compile('ab*', re.IGNORECASE)
re.A
re.ASCII
让 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配ASCII,而不是Unicode。这只对Unicode样式有效,会被byte样式忽略。相当于前面语法中的内联标志 (?a) 。
注意,为了保持向后兼容, re.U 标记依然存在(还有他的同义 re.UNICODE 和嵌入形式 (?u) ) , 但是这些在 Python 3 是冗余的,因为默认字符串已经是Unicode了(并且Unicode匹配不允许byte出现)。
re.DEBUG
显示编译时的debug信息,没有内联标记。
re.I
re.IGNORECASE
进行忽略大小写匹配;表达式如 [A-Z] 也会匹配小写字符。Unicode匹配(比如 Ü 匹配 ü)同样有用,除非设置了 re.ASCII 标记来禁用非ASCII匹配。当前语言区域不会改变这个标记,除非设置了 re.LOCALE 标记。这个相当于内联标记 (?i) 。
注意,当设置了 IGNORECASE 标记,搜索Unicode样式 [a-z] 或 [A-Z] 的结合时,它将会匹配52个ASCII字符和4个额外的非ASCII字符: ‘İ’ (U+0130, 拉丁大写的 I 带个点在上面), ‘ı’ (U+0131, 拉丁小写没有点的 I ), ‘ſ’ (U+017F, 拉丁小写长 s) and ‘K’ (U+212A, 开尔文符号).如果使用 ASCII 标记,就只匹配 ‘a’ 到 ‘z’ 和 ‘A’ 到 ‘Z’ 。
re.L
re.LOCALE
由当前语言区域决定 \w, \W, \b, \B 和大小写敏感匹配。这个标记只能对byte样式有效。这个标记不推荐使用,因为语言区域机制很不可靠,它一次只能处理一个 "习惯”,而且只对8位字节有效。Unicode匹配在Python 3 里默认启用,并可以处理不同语言。 这个对应内联标记 (?L) 。
在 3.6 版更改: re.LOCALE 只能用于byte样式,而且不能和 re.ASCII 一起用。
在 3.7 版更改: 设置了 re.LOCALE 标记的编译正则对象不再在编译时依赖语言区域设置。语言区域设置只在匹配的时候影响其结果。
re.M
re.MULTILINE
设置以后,样式字符 ‘^’ 匹配字符串的开始,和每一行的开始(换行符后面紧跟的符号);样式字符 ‘’ 匹配字符串尾。对应内联标记 (?m) 。
re.S
re.DOTALL
让 ‘.’ 特殊字符匹配任何字符,包括换行符;如果没有这个标记,’.’ 就匹配 除了 换行符的其他任意字符。对应内联标记 (?s) 。
re.X
re.VERBOSE
这个标记允许你编写更具可读性更友好的正则表达式。通过分段和添加注释。空白符号会被忽略,除非在一个字符集合当中或者由反斜杠转义,或者在 *?, (?: or (?P<…> 分组之内。当一个行内有 # 不在字符集和转义序列,那么它之后的所有字符都是注释。
意思就是下面两个正则表达式等价地匹配一个十进制数字:
a = re.compile(r"""\d + # the integral part
. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+.\d*")
对应内联标记 (?x) 。
re.search(pattern, string, flags=0)
扫描整个 字符串 找到匹配样式的第一个位置,并返回一个相应的 匹配对象。如果没有匹配,就返回一个 None ; 注意这和找到一个零长度匹配是不同的。
re.match(pattern, string, flags=0)
如果 string 开始的0或者多个字符匹配到了正则表达式样式,就返回一个相应的 匹配对象 。 如果没有匹配,就返回 None ;注意它跟零长度匹配是不同的。
注意即便是 MULTILINE 多行模式, re.match() 也只匹配字符串的开始位置,而不匹配每行开始。
如果你想定位 string 的任何位置,使用 search() 来替代(也可参考 search() vs. match() )
re.fullmatch(pattern, string, flags=0)
如果整个 string 匹配到正则表达式样式,就返回一个相应的 匹配对象 。 否则就返回一个 None ;注意这跟零长度匹配是不同的。
re.split(pattern, string, maxsplit=0, flags=0)
用 pattern 分开 string 。 如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素。
re.findall(pattern, string, flags=0)
对 string 返回一个不重复的 pattern 的匹配列表, string 从左到右进行扫描,匹配按找到的顺序返回。如果样式里存在一到多个组,就返回一个组合列表;就是一个元组的列表(如果样式里有超过一个组合的话)。空匹配也会包含在结果里。
在 3.7 版更改: 非空匹配现在可以在前一个空匹配之后出现了。
re.finditer(pattern, string, flags=0)
pattern 在 string 里所有的非重复匹配,返回为一个迭代器 iterator 保存了 匹配对象 。 string 从左到右扫描,匹配按顺序排列。空匹配也包含在结果里。
re.sub(pattern, repl, string, count=0, flags=0)
返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串。 如果样式没有找到,则不加改变地返回 string。 repl 可以是字符串或函数;如为字符串,则其中任何反斜杠转义序列都会被处理。 也就是说,\n 会被转换为一个换行符,\r 会被转换为一个回车附,依此类推。 未知的 ASCII 字符转义序列保留在未来使用,会被当作错误来处理。 其他未知转义序列例如 & 会保持原样。 向后引用像是 \6 会用样式中第 6 组所匹配到的子字符串来替换。
7. http模块
http 是一个包,它收集了多个用于处理超文本传输协议的模块:
http.client 是一个低层级的 HTTP 协议客户端;对于高层级的 URL 访问请使用 urllib.request
http.server 包含基于 socketserver 的基本 HTTP 服务类
http.cookies 包含一些有用来实现通过 cookies 进行状态管理的工具
http.cookiejar 提供了 cookies 的持久化
http 也是一个通过 http.HTTPStatus 枚举定义了一些 HTTP 状态码以及相关联消息的模块:
enum.IntEnum 的子类,它定义了组 HTTP 状态码,原理短语以及用英语书写的长描述文本。
用法:
> from http import HTTPStatus
>>> HTTPStatus.OK
<HTTPStatus.OK: 200>
>>> HTTPStatus.OK == 200
True
>>> http.HTTPStatus.OK.value
200
>>> HTTPStatus.OK.phrase
'OK'
>>> HTTPStatus.OK.description
'Request fulfilled, document follows'
>>> list(HTTPStatus)
[<HTTPStatus.CONTINUE: 100>, <HTTPStatus.SWITCHING_PROTOCOLS: 101>, ...]