其余详细内容 http://www.cnblogs.com/Eva-J/articles/7291842.html
引自:http://www.cnblogs.com/haiyan123/p/7298967.htmlhtml
认识模块python
常见模块分类 git
正则表达式正则表达式
re模块app
什么是模块:一个模块就是一个包含了python定义和声明的文件,文件名就是加上.py的后缀,但其实import加载的模块分为四个通用类别 :函数
1.使用python编写的代码(.py文件) 2.已被编译为共享库二和DLL的C或C++扩展 3.包好一组模块的包 4.使用C编写并链接到python解释器的内置模块
为什么要使用模块?工具
若是你想退出python解释器而后从新进入,那么你以前定义的函数或变量都将丢失,所以咱们一般将程序写到文件中以便永久保存下来,须要时,就经过python test.py 方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能愈来愈多,为了方便管理,咱们一般将文件分红一个个的文件,这样作程序的结构更清晰,方便管理。这时咱们不只仅能够吧这些文件当作脚本去执行,还能够把它们当作模块来导入到其余模块中,实现了功能的重复利用。
经常使用模块1、post
collocations 模块
时间模块
random模块
os模块
sys模块
序列化模块
re模块
经常使用模块二:这些模块和面向对象有关
hashlib模块
configparse模块
logging模块
像咱们日常见的那些注册页面啥的,都须要咱们输入手机号码吧,你想咱们的电话号码也是有限定的吧(手机号码一共11位,而且只以13,14,15,17,18开头的数字这些特色)若是你的输入有误就会提示,那么实现这个程序的话你以为用While循环so easy嘛,那么咱们来看看实现的结果。
while True: phone_number=input('请输入你的电话号码:') if len(phone_number)==11 and phone_number.isdigit()\ and (phone_number.startswith('13')\ or phone_number.startswith('14') \ or phone_number.startswith('15') \ or phone_number.startswith('17') \ or phone_number.startswith('18')): print('是合法的手机号码') else: print('不是合法的手机号码')
看到这个代码,虽然说理解很容易,可是我还有更简单的方法。那咱们一块儿来看看吧。
import re phone_number=input('请输入你的电话号码:') if re.match('^(13|14|15|17|18)[0-9]{9}$',phone_number): '''^这个符号表示的是判断是否是以13|14|15|17|18开头的, [0-9]: []表示一个字符组,能够表示0-9的任意字符 {9}:表示后面的数字重复九次 $:表示结束符 ''' print('是合法的手机号码') else: print('不是合法的手机号码')
你们可能都觉的第一种方法更简单吧,可是若是我让你从整个文件中匹配出全部的手机号码,你能用python写出来吗?可是导入re模块和利用正则表达式就能够解决这一个问题了。
那么什么是正则呢?
首先你要知道的是,谈到正则,就只和字符串相关了。在线测试工具 http://tool.chinaz.com/regex/
好比你要用‘1’去匹配‘1’,或者用‘2’去匹配‘2’,直接就能够匹配上。
字符组:[字符组]
在同一位置可能出现的各类字符组成了一个字符组,在正则表达式中用[]表示
字符分为不少类,好比数字,字母,标点等。
假如你如今要求一个位置‘只能出现一个数字’,那么这个位置上的字符只能是0、一、二、3.......9这是个数之一。
字符组:
字符:
量词:
.^$
*+?{}
注意:前面的*,+,?等都是贪婪匹配,也就是尽量多的匹配,后面加?就变成了非贪婪匹配,也就是惰性匹配。
贪婪匹配:
几个经常使用的贪婪匹配
*?;重复任意次,但尽量少重复 +?:重复一次或更屡次,但尽量少重复 ??:重复0次或1次,但尽量少重复 {n,m}:重复n到m次,但尽量少重复 {n,}: 重复n次以上,但尽量少重复
.*?的用法:
.是任意字符 *是取0到无限长度 ?是非贪婪模式 和在一块儿就是取尽可能少的任意字符,通常不会这么单独写,大多用在: .*?x 意思就是取前面任意长度的字符,直到一个x出现
字符集:
分组()与或|[^]:
(1)^[1-9]\d{13,16}[0-9x]$ #^以数字0-9开始, \d{13,16}重复13次到16次 $结束标志 上面的表达式能够匹配一个正确的身份证号码 (2)^[1-9]\d{14}(\d{2}[0-9x])?$ #?重复0次或者1次,当是0次的时候是15位,是1的时候是18位 (3)^([1-9]\d{16}[0-9x]|[1-9]\d{14})$ #表示先匹配[1-9]\d{16}[0-9x]若是没有匹配上就匹配[1-9]\d{14}
举个例子,好比html源码中有<title>xxx</title>标签,用之前的知识,咱们只能肯定源码中的<title>和</title>是固定不变的。所以,若是想获取页面标题(xxx),充其量只能写一个相似于这样的表达式:<title>.*</title>,而这样写匹配出来的是完整的<title>xxx</title>标签,并非单纯的页面标题xxx。 想解决以上问题,就要用到断言知识。 在讲断言以前,读者应该先了解分组,这有助于理解断言。 分组在正则中用()表示,根据小菜理解,分组的做用有两个: n 将某些规律当作是一组,而后进行组级别的重复,能够获得意想不到的效果。 n 分组以后,能够经过后向引用简化表达式。 先来看第一个做用,对于IP地址的匹配,简单的能够写为以下形式: \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} 但仔细观察,咱们能够发现必定的规律,能够把.\d{1,3}当作一个总体,也就是把他们当作一组,再把这个组重复3次便可。表达式以下: \d{1,3}(.\d{1,3}){3} 这样一看,就比较简洁了。 再来看第二个做用,就拿匹配<title>xxx</title>标签来讲,简单的正则能够这样写: <title>.*</title> 能够看出,上边表达式中有两个title,彻底同样,其实能够经过分组简写。表达式以下: <(title)>.*</\1> 这个例子实际上就是反向引用的实际应用。对于分组而言,整个表达式永远算做第0组,在本例中,第0组是<(title)>.*</\1>,而后从左到右,依次为分组编号,所以,(title)是第1组。 用\1这种语法,能够引用某组的文本内容,\1固然就是引用第1组的文本内容了,这样一来,就能够简化正则表达式,只写一次title,把它放在组里,而后在后边引用便可。 以此为启发,咱们可不能够简化刚刚的IP地址正则表达式呢?原来的表达式为\d{1,3}(.\d{1,3}){3},里边的\d{1,3}重复了两次,若是利用后向引用简化,表达式以下: (\d{1,3})(.\1){3} 简单的解释下,把\d{1,3}放在一组里,表示为(\d{1,3}),它是第1组,(.\1)是第2组,在第2组里经过\1语法,后向引用了第1组的文本内容。 通过实际测试,会发现这样写是错误的,为何呢? 小菜一直在强调,后向引用,引用的仅仅是文本内容,而不是正则表达式! 也就是说,组中的内容一旦匹配成功,后向引用,引用的就是匹配成功后的内容,引用的是结果,而不是表达式。 所以,(\d{1,3})(.\1){3}这个表达式实际上匹配的是四个数都相同的IP地址,好比:123.123.123.123。 至此,读者已经掌握了传说中的后向引用,就这么简单。
分组命名:语法(?p<name>)注意先命名,后正则
import re import re ret=re.search('<(\w+)>\w+<(/\w+)>','<h1>hello</h1>') print(ret.group()) # 给分组起个名字。就用下面的分组命名,上面的方法和下面的分组命名是同样的,只不过就是给命了个名字 ret=re.search('<(?P<tag_name>\w+)>\w+</(?P=tag_name)>','<h1>hello</h1>') #(?P=tag_name)就表明的是(\w+) print(ret.group()) # 了解(和上面的是同样的,是上面方式的那种简写) ret=re.search(r'<(\w+)>\w+</\1>','<h1>hello</h1>') print(ret.group(1))
转义符:
# 1.re模块下的经常使用方法 # 1.findall方法 import re ret = re.findall('a','eva ang egons') # #返回全部知足匹配条件的结果,放在列表里 print(ret) # 2.search方法 # 函数会在字符串中查找模式匹配,只会找到第一个匹配而后返回 # 一个包含匹配信息的对象,该对象经过调用group()方法获得匹配的 # 字符串,若是字符串没有匹配,则报错 ret = re.search('s','eva ang egons')#找第一个 print(ret.group()) # 3.match方法 print(re.match('a','abc').group()) #同search,只从字符串开始匹配,而且guoup才能找到 # 4.split方法 print(re.split('[ab]','abcd')) #先按'a'分割获得''和'bcd',在对''和'bcd'分别按'b'分割 # 5.sub方法 print(re.sub('\d','H','eva3sdf4ahi4asd45',1)) # 将数字替换成'H',参数1表示只替换一个 # 6.subn方法 print(re.subn('\d','H','eva3sdf4ahi4asd45')) #将数字替换成’H‘,返回元组(替换的结果,替换了多少次) # 7.compile方法 obj = re.compile('\d{3}')#将正则表达式编译成一个正则表达式对象,规则要匹配的是三个数字 print(obj) ret = obj.search('abc12345eeeee')#正则表达式对象调用search,参数为待匹配的字符串 print(ret.group()) #.group一下就显示出结果了 # 8.finditer方法 ret = re.finditer('\d','dsf546sfsc')#finditer返回的是一个存放匹配结果的迭代器 # print(ret)#<callable_iterator object at 0x00000000021E9E80> print(next(ret).group())#查看第一个结果 print(next(ret).group())#查看第二个结果 print([i.group() for i in ret] )#查看剩余的左右结果
import re ret = re.findall('www.(baidu|oldboy).com','www.oldboy.com') print(ret) #结果是['oldboy']这是由于findall会优先把匹配结果组里内容返回,若是想要匹配结果,取消权限便可 ret = re.findall('www.(?:baidu|oldboy).com','www.oldboy.com') print(ret) #['www.oldboy.com']
ret = re.split('\d+','eva123dasda9dg')#按数字分割开了 print(ret) #输出结果:['eva', 'dasda', 'dg'] ret = re.split('(\d+)','eva123dasda9dg') print(ret) #输出结果:['eva', '123', 'dasda', '9', 'dg'] # # 在匹配部分加上()以后和不加括号切出的结果是不一样的, # 没有括号的没有保留所匹配的项,可是有括号的却可以保留了 # 匹配的项,这个在某些须要保留匹配部分的使用过程是很是重要的
re模块和正则表达式没有一点毛线关系。re模块和正则表达式的关系相似于time模块和时间的关系,你没有学习python以前,也不知道有一个time模块,可是你已经认识时间了呀,12:30就表示中午十二点半。时间有本身的格式,年月日时分秒,已成为一种规则。你早就牢记于心了,time模块只不过是python提供给咱们的能够方便咱们操做时间的一个工具而已。
在内置数据类型(dict,list,set,tuple)的基础上,collections 模块还提供了几个额外的数据类型:
1.namedtuple:生成可使用名字来访问元素内容的tuple 2.deque:双向队列(两头均可进可出,可是不能取中间的值),能够快速的从另一侧追加和推出对象 3.Counter:计数器,主要用来计数 4.OrderedDict:有序字典 5.defaultdict:带有默认值的字典
namedtuple:
咱们知道tuple能够表示不变集合,例如,一个点的二维坐标就能够表示成:p=(1,2)
可是,看到(1,2),很难看出这个tuple是用来表示坐标的。
那么,咱们的namedtuple就能用上了。
namedtuple('名称',‘属性list’)
from collections import namedtuple point = namedtuple('point',['x','y']) p = point(1,2) print(p.x,p.y)、<br><br><br>
Circle = namedtuple('Circle', ['x', 'y', 'r'])#用坐标和半径表示一个圆
deque
单向队列<br># import queue #队列模块 # q = queue.Queue() # q.put(10) # q.put(20) # q.put(30) # # 10 20 30 # print(q.get()) # print(q.get()) # print(q.get()) # print(q.get())
deque是为了高效实现插入和删除操做的双向队列,适用于队列和栈
from collections import deque q = deque(['a','b','c']) q.append('ee')#添加元素 q.append('ff') q.append('qq') print(q) q.appendleft('www')#从左边添加 print(q) q.pop() #删除元素 q.popleft() #从左边删除元素 print(q)
OrderedDict
使用字典时,key是无序的。在对字典作迭代时,咱们没法肯定key的顺序。若是要保持key的顺序,能够用OrderedDict
from collections import OrderedDict
d = {'z':'qww','x':'asd','y':'asd','name':'alex'} print(d.keys()) #key是无序的
od = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) print(od)# OrderedDict的Key是有序的 <br>OrderedDict([('a', 1), ('b', 2), ('c', 3)])<br><br><br>
注意,OrderedDict的Key会按照插入的顺序排列,不是Key自己排序:
od = OderedDict () od['z']=1 od['y']=2 od['x']=3 print(od.keys()) #按照插入额key的顺序返回
defaultdict
d = {'z':'qww','x':'asd','y':'asd','name':'alex'} print(d.keys()) from collections import defaultdict values = [11,22,33,44,55,66,77,88,99] my_dict = defaultdict(list) for v in values: if v>66: my_dict['k1'].append(v) else: my_dict['k2'].append(v) print(my_dict)
from collections import defaultdict dd = defaultdict(lambda: 'N/A') dd['key1'] = 'abc' print(dd['key1']) # key1存在 print(dd['key2']) # key2不存在,返回默认值
Counter
Counter类的目的是用来跟踪值出现的次数。它是一个无序的容器类型,以字典的键值对形式存储,其中元素做为key,其计数做为value。计数值能够是任意的Interger(包括0和负数)。Counter类和其余语言的bags或multisets很类似。
from collections import Counter c = Counter('abcdeabcdabcaba') print(c) # 输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})