python基础_模块

模块:一个个定义了许多函数的.py文件

模块分为三种:

1.python标准库

2.第三方模块库

3.应用程序的自定义模块

使用模块可以避免函数和变量名的冲突,因为同名函数可以分布在不同的模块,而同名变量可以分布在不同的模块和函数中,因此我们在编程时,不必考虑名字会与其他模块冲突。但是也要注意,不要与内置的函数名字冲突。

模块导入:

1.import 语句
import module1[, module2[,... moduleN]
2.fromimport 语句
from modname import name1[, name2[, ... nameN]]
3.From…import* 语句
from modname import *

通过运行 print(sys.path) ,可以打印python解释器在导入模块时的搜索路径。

模块导入语句的运行本质:

#1 import test
#2 from test import add  
无论1还是2,首先通过sys.path找到test.py,然后执行test脚本(全部执行),区别是1会将test这个变量名加载到名字空间,而2只会将add这个变量名加载进来。

包:

1.必须含有__init__.py文件,否则python解释器会把该目录当成普通目录,而不是一个包。

2.__init__.py可以是空文件,也可以有Python代码,因为__init__.py本身就是一个模块,而它的模块名就是对应包的名字。导入包,就是执行包下的__init__.py文件。

3.包可以解决模块同名问题,即同名模块可以放入不同的包中。

找不到模块:

就要把模块所在的路径加到导入模块时,python解释器的搜索路径。

import sys,os
BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASE_DIR)
os.path.abspath(
__file__):获得被执行文件的绝对路径 os.path.dirname(os.path.abspath(__file__)):获得被执行文件的所在目录(即被执行文件的上一级目录) os.path.dirname(os.path.dirname(os.path.abspath(__file__))):获得被执行文件的所在目录的上一级目录(即被执行文件的上两级目录)

if __name__=='__mian__': 作用:

1.在被执行文件中,打印__name__时,返回值是__main__,即在被执行文件中就相当于if True:

2.在被调用文件中,打印__name__时,返回值是被调用文件的名字,即在被调用文件中就相当于if False:

返回的被调用文件的名字分为两种:

1.若是同级目录,就是名字,若是 import re1 ,返回re1。

2.若不是同级目录,则是相对路径加名字,中间用点连接,若是 from web.web1 import re1 ,返回web.web1.re1。

time模块

1.时间戳(timestamp):时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。

2.结构化时间:struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)

3.格式化的时间字符串

import time
# 1 time() :返回当前时间的时间戳
print(time.time())
1528607515.4653292

# 2 localtime([secs])
# 将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。
print(time.localtime())
print(time.localtime(1473525444))
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=10, tm_hour=13, tm_min=11, tm_sec=55, tm_wday=6, tm_yday=161, tm_isdst=0)
time.struct_time(tm_year=2016, tm_mon=9, tm_mday=11, tm_hour=0, tm_min=37, tm_sec=24, tm_wday=6, tm_yday=255, tm_isdst=0)

# 3 gmtime([secs]) 和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。
print(time.gmtime())
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=10, tm_hour=5, tm_min=11, tm_sec=55, tm_wday=6, tm_yday=161, tm_isdst=0)

# 4 mktime(t) : 将一个struct_time转化为时间戳。
print(time.mktime(time.localtime()))
1528607515.0

# 5 asctime([t]) : 把一个表示时间的元组或者struct_time表示为这种形式:'Sun Jun 20 23:21:05 1993'。
# 如果没有参数,将会将time.localtime()作为参数传入。
print(time.asctime())
Sun Jun 10 13:11:55 2018

# 6 ctime([secs]) : 把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。如果参数未给或者为
# None的时候,将会默认time.time()为参数。它的作用相当于time.asctime(time.localtime(secs))。
print(time.ctime())
print(time.ctime(time.time()))
Sun Jun 10 13:11:55 2018
Sun Jun 10 13:11:55 2018

# 7 strftime(format[, t]) : 把一个代表时间的元组或者struct_time(如由time.localtime()和
# time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个
# 元素越界,ValueError的错误将会被抛出。
print(time.strftime("%Y-%m-%d %X", time.localtime()))
2018-06-10 13:11:55

# 8 time.strptime(string[, format])
# 把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。
#在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"。
print(time.strptime('2018-06-10 13:11:55', '%Y-%m-%d %X'))
time.struct_time(tm_year=2018, tm_mon=6, tm_mday=10, tm_hour=13, tm_min=11, tm_sec=55, tm_wday=6, tm_yday=161, tm_isdst=-1)# 9 sleep(secs)
# 线程推迟指定的时间运行,单位为秒。
# 10 clock()
# 这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。
# 而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行
# 时间,即两次时间差。

random模块

import random
print(random.random()) #输出为[0,1)之间的浮点数
0.34047066573019424

print(random.randint(1,3)) #输出为[1,3]之间的整数
3

print(random.randrange(1,3)) #输出为[1,3)之间的整数
2

print(random.choice([11,22,33,44,55])) #输出为列表中的任一值
33

print(random.sample([11,22,33,44,55],2)) #输出为列表中任意两个组成的列表
[11, 33]

print(random.uniform(1,4)) #输出为[1,4]之间的浮点数
2.8379829087787747

ret=[1,2,3,4,5]
random.shuffle(ret) #将ret序列打乱
print(ret)
[5, 1, 3, 4, 2]

os模块

os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")  改变当前脚本工作目录;相当于shell下cd
os.curdir  返回当前目录: ('.')
os.pardir  获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2')    可生成多层递归目录
os.removedirs('dirname1')    若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')    生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')    删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')    列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()  删除一个文件
os.rename("oldname","newname")  重命名文件/目录
os.stat('path/filename')  获取文件/目录信息
os.sep    输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep    输出当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep    输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name    输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")  运行shell命令,直接显示
os.environ  获取系统环境变量
os.path.abspath(path)  返回path规范化的绝对路径
os.path.split(path)  将path分割成目录和文件名二元组返回
os.path.splitext(path)  分割路径,返回路径名和文件扩展名的元组 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False os.path.isabs(path) 如果path是绝对路径,返回True os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间
os.path.expanduser(path)  把path中包含的"~"和"~user"转换成用户目录

sys模块

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
import sys
print(sys.argv)
command=sys.argv[1]
path=sys.argv[2]
if command=="post":
    print('post')
elif command=="get":
    print('get')
print(path)

['.\\sys_test.py', 'get', './']
get
./

(命令行中执行该文件)

json模块

序列化:将对象(变量)转或换成可存储或可传输的过程,序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络,传输到别的机器上。

反序列化:将序列化后的对象重新读入到内存中。

JSON类型-------->Python类型

{}-------->dict

[]-------->list

"string"-------->str

1234.56-------->int或float

true/flase-------->True/Flase

null-------->None

#----------------------------序列化
import json
dic={'name':'alvin','age':23,'sex':'male'}
print(type(dic))#<class 'dict'>
j=json.dumps(dic)
print(type(j))#<class 'str'>
f=open('序列化对象','w')
f.write(j)  #-------------------等价于json.dump(dic,f)
f.close()
#-----------------------------反序列化
import json
f=open('序列化对象')
data=json.loads(f.read())#  等价于data=json.load(f)

注意:

1.json字符串只认" "双引号

2.无论数据是怎样创建的,只要满足json格式,就可以json.loads出来,不一定非要dumps的数据才能loads

pickle模块

##----------------------------序列化
import pickle
dic={'name':'alvin','age':23,'sex':'male'}
print(type(dic))#<class 'dict'>
j=pickle.dumps(dic)
print(type(j))#<class 'bytes'>
f=open('序列化对象_pickle','wb')#注意是w是写入str,wb是写入bytes,j是'bytes'
f.write(j)  #-------------------等价于pickle.dump(dic,f)
f.close()
#-------------------------反序列化
import pickle
f=open('序列化对象_pickle','rb')
data=pickle.loads(f.read())#  等价于data=pickle.load(f)
print(data['age'])

Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。

shelve模块

import shelve

f = shelve.open(r'shelve.txt')

# f['stu1_info']={'name':'alex','age':'18'}
# f['stu2_info']={'name':'alvin','age':'20'}
# f['school_info']={'website':'oldboyedu.com','city':'beijing'}
# f.close()

print(f.get('stu1_info')['age'])
18

 shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型。

xml模块

跟json模块差不多,实现不同语言和程序之间进行数据交换的协议。

xml数据格式如下:

xml数据:

<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

python中操作xml模块:

import xml.etree.ElementTree as ET

tree = ET.parse("xml_data.xml")
root = tree.getroot()
print(root.tag)

#遍历xml文档
for child in root:
    print(child.tag, child.attrib)
    for i in child:
        print(i.tag,i.text)

#只遍历year 节点
for node in root.iter('year'):
    print(node.tag,node.text)
import xml.etree.ElementTree as ET

tree = ET.parse("xml_data.xml")
root = tree.getroot()

#修改
for node in root.iter('year'):
    new_year = int(node.text) + 1
    node.text = str(new_year)
    node.set("updated","yes")

tree.write("xmltest.xml")


#删除node
for country in root.findall('country'):
   rank = int(country.find('rank').text)
   if rank > 50:
     root.remove(country)

tree.write('output.xml')

创建xml文档:

import xml.etree.ElementTree as ET
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
age = ET.SubElement(name, "age", attrib={"checked": "no"})
sex = ET.SubElement(name, "sex")
sex.text = '33'
name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
age = ET.SubElement(name2, "age")
age.text = '19'
et = ET.ElementTree(new_xml)  # 生成文档对象
et.write("test.xml", encoding="utf-8", xml_declaration=True)

ET.dump(new_xml)  # 打印生成的格式

<namelist><name enrolled="yes"><age checked="no" /><sex>33</sex></name><name enrolled="no"><age>19</age></name></namelist>

configparser模块

import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval': '45',
                     'Compression': 'yes',
                     'CompressionLevel': '9'}
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022'  # mutates the parser
topsecret['ForwardX11'] = 'no'  # same here
config['DEFAULT']['ForwardX11'] = 'yes'
with open('example.ini', 'w') as configfile:
    config.write(configfile)

生成如下格式文档:

[DEFAULT]
serveraliveinterval = 45
compression = yes
compressionlevel = 9
forwardx11 = yes

[bitbucket.org]
user = hg

[topsecret.server.com]
host port = 50022
forwardx11 = no

对文档进行增删改查

import configparser
config = configparser.ConfigParser()
#---------------------------------------------查
print(config.sections())   #[]
config.read('example.ini')
print(config.sections())   #['bitbucket.org', 'topsecret.server.com']
print('bytebong.com' in config)# False
print(config['bitbucket.org']['User']) # hg
print(config['DEFAULT']['Compression']) #yes
print(config['topsecret.server.com']['ForwardX11'])  #no
for key in config['bitbucket.org']:
    print(key)  
# user
# serveraliveinterval
# compression
# compressionlevel
# forwardx11
print(config.options('bitbucket.org'))#['user', 'serveraliveinterval', 'compression', 'compressionlevel', 'forwardx11']
print(config.items('bitbucket.org'))  #[('serveraliveinterval', '45'), ('compression', 'yes'), ('compressionlevel', '9'), ('forwardx11', 'yes'), ('user', 'hg')]
print(config.get('bitbucket.org','compression'))#yes
#---------------------------------------------删,改,增(config.write(open('i.cfg', "w")))
config.add_section('yuan')
config.remove_section('topsecret.server.com')
config.remove_option('bitbucket.org','user')
config.set('bitbucket.org','k1','11111')
config.write(open('i.cfg', "w"))

hashlib模块

import hashlib
m=hashlib.md5()# m=hashlib.sha256()
m.update('hello'.encode('utf8'))
print(m.hexdigest())  #5d41402abc4b2a76b9719d911017c592
m.update('alvin'.encode('utf8'))
print(m.hexdigest())  #92a7e713c30abbb0319fa07da2a5c4af

m2=hashlib.md5()
m2.update('helloalvin'.encode('utf8'))
print(m2.hexdigest()) #92a7e713c30abbb0319fa07da2a5c4af

以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。

用于加密相关的操作,python3.x主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

logging模块

import logging
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S',
                    filename='E:\\1_python_code\\code\\LNH_python_3\\day23\\test.log',
                    filemode='w')

logging.debug('debug message')
logging.info('info message')
logging.warning('warning message')
logging.error('error message')
logging.critical('critical message')

test.log文件内容:

Sun, 10 Jun 2018 16:03:49 my_logging.py[line:16] DEBUG debug message
Sun, 10 Jun 2018 16:03:49 my_logging.py[line:17] INFO info message
Sun, 10 Jun 2018 16:03:49 my_logging.py[line:18] WARNING warning message
Sun, 10 Jun 2018 16:03:49 my_logging.py[line:19] ERROR error message
Sun, 10 Jun 2018 16:03:49 my_logging.py[line:20] CRITICAL critical message

logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open('test.log','w')),默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。

format参数中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s用户输出的消息

import logging
logger = logging.getLogger()
# 创建一个handler,用于写入日志文件
fh = logging.FileHandler('test.log')
# 再创建一个handler,用于输出到控制台
ch = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 定义一个filter
filter = logging.Filter('mylogger')
fh.addFilter(filter)
ch.addFilter(filter)
# logger.addFilter(filter)
logger.addHandler(fh)
logger.addHandler(ch)
logger.setLevel(logging.DEBUG)
logger.debug('logger debug message')
logger.info('logger info message')
logger.warning('logger warning message')
logger.error('logger error message')
logger.critical('logger critical message')
##################################################
logger1 = logging.getLogger('mylogger')
logger1.setLevel(logging.DEBUG)
logger2 = logging.getLogger('mylogger')
logger2.setLevel(logging.INFO)
logger1.addHandler(fh)
logger1.addHandler(ch)
logger2.addHandler(fh)
logger2.addHandler(ch)
logger1.debug('logger1 debug message')
logger1.info('logger1 info message')
logger1.warning('logger1 warning message')
logger1.error('logger1 error message')
logger1.critical('logger1 critical message')
logger2.debug('logger2 debug message')
logger2.info('logger2 info message')
logger2.warning('logger2 warning message')
logger2.error('logger2 error message')
logger2.critical('logger2 critical message')

注释掉filter,显示效果如下:

不注释掉filter,效果如下:

可以发现:

1.logger是一个树形层级结构

2.logger = logging.getLogger()返回的Logger名为root

3.通过logger.setLevel(logging.Debug)设置日志显示的级别,只有大于等于设置的级别才会显示,日志级别从低到高logging.Debug、logging.Info、logging.Warning、logging.Error、logging.Critical

4.Filter限制只有满足过滤规则的日志才会输出。

     filter = logging.Filter('mylogger') 

     logger.addFilter(filter)

     这是只对logger这个对象进行筛选

     如果想对所有的对象进行筛选,则:

      filter = logging.Filter('mylogger') 

      fh.addFilter(filter)

      ch.addFilter(filter)

这样,所有添加fh或者ch的logger对象都会进行筛选。

显示的两个问题:

1.我们明明通过logger1.setLevel(logging.DEBUG)将logger1的日志级别设置为了DEBUG,为何显示的时候没有显示出DEBUG级别的日志信息,而是从INFO级别的日志开始显示呢?

原来logger1和logger2对应的是同一个Logger实例,只要logging.getLogger(name)中名称参数name相同则返回的Logger实例就是同一个,且仅有一个,也即name与Logger实例一一对应。在logger2实例中通过logger2.setLevel(logging.INFO)设置mylogger的日志级别为logging.INFO,所以最后logger1的输出遵从了后来设置的日志级别。

2.为什么logger1、logger2对应的每个输出分别显示两次?

这是因为我们通过logger = logging.getLogger()显示的创建了root Logger,而logger1 = logging.getLogger('mylogger')创建了root Logger的孩子(root.)mylogger,logger2同样。而孩子,孙子,重孙……既会将消息分发给他的handler进行处理也会传递给所有的祖先Logger处理。

现在把

# logger.addHandler(fh)

# logger.addHandler(ch)  注释掉,我们再来看效果:

因为我们注释了logger对象显示的位置,所以才用了默认方式,即标准输出方式。因为它的父级没有设置文件显示方式,所以在这里只打印了一次。

re模块

正则表达式(RE)本质上,就是一种小型的高度专业化的编程语言,它内嵌在Python中,并通过re模块实现。正则表达式模式被编译成一系列的字节码,然后由C编写的匹配引擎执行。

字符匹配(普通字符,元字符)

1.普通字符:大多数字符和字母都会和自身匹配

re.findall('alex', 'ghgkyjhgalexbhkjglioh')
['alex']

2.元字符:.  ^  $  *  +  ?  {}  []  |  ()  \

.--------------->可以代替一位,表示任意

^alex--------------->表示以alex开头

alex$--------------->表示以alex结尾

alex*--------------->表示含有ale,x可以出现0到无穷次,ale,alex,alexx,alexxx......

alex+--------------->表示含有ale,x可以出现1到无穷次,alex,alexx,alexxx..........

alex?--------------->表示含有ale,x可以出现0到1次,即:ale或alex

*,+,?都是贪婪匹配,尽可能多的匹配,后再加个问号,就变成惰性匹配

alex*?--------------->表示含有ale,x可以出现0,ale

alex+?--------------->表示含有ale,x可以出现1,alex

alex??--------------->表示含有ale,x可以出现0,即:ale

alex{1,4}--------------->表示含有ale,x可以出现1到4次,也是贪婪匹配,尽可能多的匹配

|--------------->表示匹配|左右表达式任意一个,从左到右匹配

()--------------->表示()内的是一个整体,若()内有|,则仅在()内有效

(? )括号里加问号可以取消优先级

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']

特殊的分组:(最后一栏为匹配的对象)

[]--------------->在[]内的元素都相当于是‘或’的关系,^符号在[]中表示取反的意思^a--------------->表示不含a

                      -符号在[]中表示取一段的意思a-z--------------->表示a到z

                      \符号在[]中的意思和不在[]中的意思一样,见下

\--------------->转义字符:1.反斜杠后边跟元字符去除特殊功能,比如\.  2.反斜杠后边跟普通字符实现特殊功能,比如\d

\d  匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s  匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b  匹配一个特殊字符边界,比如空格 ,&,#等

#-----------------------------eg1:
import re
ret=re.findall('c\l','abc\le')
print(ret)#[]
ret=re.findall('c\\l','abc\le')
print(ret)#[]
ret=re.findall('c\\\\l','abc\le')
print(ret)#['c\\l']
ret=re.findall(r'c\\l','abc\le')
print(ret)#['c\\l']

#-----------------------------eg2:
#之所以选择\b是因为\b在ASCII表中是有意义的
m = re.findall('\bblow', 'blow')
print(m)#[]
m = re.findall(r'\bblow', 'blow')
print(m)#['blow']

r表示python解释器不进行转义,拿到什么就给正则什么。

re模块中常用的功能函数:

1.compile()  编译正则表达式模式,返回一个对象的模式。(可以把那些常用的正则表达式编译成正则表达式对象,这样可以提高一点效率。)

格式: re.compile(pattern,flags=0)

    pattern: 编译时用的表达式字符串。

    flags 编译标志位,用于修改正则表达式的匹配方式,如:是否区分大小写,多行匹配等。

常用的flags有:

import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt))   #查找所有包含'oo'的单词
执行结果如下:
['good', 'cool']

2.match()  决定RE是否在字符串刚开始的位置匹配。//注:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'

格式: re.match(pattern, string, flags=0)

print(re.match('com','comwww.runcomoob').group())
print(re.match('com','Comwww.runcomoob',re.I).group())
执行结果如下:
com
com

3.search()   re.search函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。

格式: re.search(pattern, string, flags=0)

print(re.search('\dcom','www.4comrunoob.5com').group())
执行结果如下:
4com

*注:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:

  • group() 返回被 RE 匹配的字符串
  • start() 返回匹配开始的位置
  • end() 返回匹配结束的位置
  • span() 返回一个元组包含匹配 (开始,结束) 的位置
  • group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。

a. group()返回re整体匹配的字符串,
b. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
c.groups()groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则表达式中定义的组。 

import re
a = "123abc456"
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0))   #123abc456,返回整体
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1))   #123
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2))   #abc
 print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3))   #456
###group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。###

4.split()  按照能够匹配的子串将string分割后返回列表。

格式: re.split(pattern, string[, maxsplit])

    maxsplit用于指定最大分割次数,不指定将全部分割。

print(re.split('\d+','one1two2three3four4five5'))
执行结果如下:
['one', 'two', 'three', 'four', 'five', '']

可以使用re.split来分割字符串,如:re.split(r'\s+', text);将字符串按空格分割成一个单词列表。

5.sub()  

使用re替换string中每一个匹配的子串后返回替换后的字符串。

格式: re.sub(pattern, repl, string, count)

import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', '-', text))
执行结果如下:
JGood-is-a-handsome-boy,-he-is-cool,-clever,-and-so-on...
其中第二个函数是替换后的字符串;本例中为'-'
第四个参数指替换个数。默认为0,表示每个匹配项都替换。

re.sub还允许使用函数对匹配项的替换进行复杂的处理。

如:re.sub(r'\s', lambda m: '[' + m.group(0) + ']', text, 0);将字符串中的空格' '替换为'[ ]'。

import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
print(re.sub(r'\s+', lambda m:'['+m.group(0)+']', text,0))
执行结果如下:
JGood[ ]is[ ]a[ ]handsome[ ]boy,[ ]he[ ]is[ ]cool,[ ]clever,[ ]and[ ]so[ ]on...

6.subn()  返回替换次数

格式: subn(pattern, repl, string, count=0, flags=0)

print(re.subn('[1-2]','A','123456abcdef'))
print(re.sub("g.t","have",'I get A,  I got B ,I gut C'))
print(re.subn("g.t","have",'I get A,  I got B ,I gut C'))
执行结果如下:
('AA3456abcdef', 2)
I have A,  I have B ,I have C
('I have A,  I have B ,I have C', 3)

7.findall()  re.findall遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表。

 格式: re.findall(pattern, string, flags=0)

p = re.compile(r'\d+')
print(p.findall('o1n2m3k4'))
执行结果如下:
['1', '2', '3', '4']

import re
tt = "Tina is a good girl, she is cool, clever, and so on..."
rr = re.compile(r'\w*oo\w*')
print(rr.findall(tt))
print(re.findall(r'(\w)*oo(\w)',tt))#()表示子表达式 
执行结果如下:
['good', 'cool']
[('g', 'd'), ('c', 'l')]

8.finditer()   搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。找到 RE 匹配的所有子串,并把它们作为一个迭代器返回。

格式: re.finditer(pattern, string, flags=0)

iter = re.finditer(r'\d+','12 drumm44ers drumming, 11 ... 10 ...')
for i in iter:
    print(i)
    print(i.group())
    print(i.span())
执行结果如下:
<_sre.SRE_Match object; span=(0, 2), match='12'>
12
(0, 2)
<_sre.SRE_Match object; span=(8, 10), match='44'>
44
(8, 10)
<_sre.SRE_Match object; span=(24, 26), match='11'>
11
(24, 26)
<_sre.SRE_Match object; span=(31, 33), match='10'>
10
(31, 33)

re.match与re.search与re.findall的区别:

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

a=re.search('[\d]',"abc33").group()
print(a)
p=re.match('[\d]',"abc33")
print(p)
b=re.findall('[\d]',"abc33")
print(b)
执行结果:
3
None
['3', '3']

用flags时遇到的小坑

print(re.split('a','1A1a2A3',re.I))#输出结果并未能区分大小写
这是因为re.split(pattern,string,maxsplit,flags)默认是四个参数,当我们传入的三个参数的时候,系统会默认re.I是第三个参数,所以就没起作用。如果想让这里的re.I起作用,写成flags=re.I即可。 

 

posted @ 2018-06-10 20:27  Liu呵呵  阅读(112)  评论(0)    收藏  举报