一、装饰器
装饰器::: 本质 是函数,功能是为了装饰其它函数。就是为其他函数添加附加功能
原则 1.不能修改被装饰的函数的源代码
2.不能修改被装饰的函数的调用方式
实现装饰器知识储备:
1.函数即“变量”
变量存在在内存当中,变量的回收机制,当没有引用的时候,就回收变量
2.高阶函数
a、把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
b、返回值中包含函数(不修改函数的调用方式)
3.嵌套函数
函数进行嵌套
高阶函数+嵌套函数=》装饰器
def logger():
print("log is here!")
def test1():
pass
logger()
def test2():
pass
logger()
test1()
test2()
'''
def timmer(func):
def warpper(*args,**kwargs):
start_time = time.time()
func()
stop_time = time.time()
print("The func run time is %s" %(stop_time-start_time))
return warpper
@timmer
def test1():
time.sleep(3)
print("In the test1")
test1()
'''decorator 装饰器 语法糖
高级装饰器:
网站--页面(一个网站一个函数)100个页面不需要登录
现20个需要登录才能访问
'''
user,passwd = "alex","abc_123"
def auth1(func):
def wrapper(*args,**kwargs):
username = input("Username").strip()
password = input("Password").strip()
if user == username and passwd == password:
print("welcome!")
return func(*args,**kwargs)
return wrapper
def index(): #不需要登录
print("welcome to index page")
@auth1
def home(): #需要登录
print("welcome to home page")
home()
二、生成器
'''列表生成器'''
a = [1,2,3,4]
#列表生成式
b = [i*2 for i in range(10)]
c = []
for i in range(10):
c.append(i*2)
print(a,b,c)
'''生成器 generator g = (i**2 for i in range(10))
1、只有在调用时才会生成相应的数据 。
2、只记住当前位置
3、只有一个3.0 __next__()【2.7 next()】方法
如果全部展示
只能用for 循环全部调用
可以使用函数生成 主要是 yield 关键字
把什么返回到外面,就把yeild关键字放到那边
yeild返回函数当前的值
'''
def fib(max):
n,a,b =0,0,1
while n<max:
#print(b)
yield b
a,b =b,a+b
n=n+1
return("done")
f = fib(10)
# for j in fibg:
# print(fibg.__next__())
while True:
try:
print(f.__next__())
except StopIteration as e:
print("Generator return value:" ,e.value)
break
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# Auther:Xll
'''协程'''
import time
def consumer(name):
print("%s 准备吃包子了!" %name)
while True:
baozi = yield
print("包子【%s】个来了,被【%s】吃了!" %(baozi,name))
# c = consumer("Chenronghua")
# c.__next__()
# c.send("白菜大葱")
def producter(name):
c = consumer("Alex")
c1 = consumer("Wutengnan")
c.__next__()
c1.__next__()
print("%s宣布:吃包子大赛开始!" %name)
for i in range(10):
time.sleep(i)
print("做了%s个包子" %((i+1)*2))
c.send(i+1)
c1.send(i+1)
producter("Oldboy")
三、迭代器
可以用于 for 循环的对象,叫可迭代对象Iterable
可以被next 函数调用并不断返回下一个值得对象称为 迭代器
dir() 查看这个数据的所有方法
from collections import Iterator Iterable
isstance([],Iterable)
迭代器标示的是一个数据流
生成器 是可迭代对象,
通过Iter()方法可以把 列表、字典,字符串 变成迭代器
四、常用内置模块
#! /usr/bin/env python
# -*- coding:utf-8 -*-
# Auther:Xll
'''内置方法'''
#all 内部元素所有为真,返回真
print(all([111,1,2,3,-1]))
#any 内部任意元素为真,返回真
print(any([0,1,False]))
#内部数据转为可打印的字符串形式,中文转为unicode格式
s=[1,2,3,45,6,7,8,90,67]
s.append('开外挂')
print(ascii(s))
#bin 整数 10进制转2进制
print(bin(64))
#bool() 判断真假 0 空列表,空字典为假,其他为真
print(bool(False))
#转换位bit格式
a = bytes("abcde",encoding="utf-8")
print(a.capitalize(),a)
#bytearray 变为可列表,可操作列表来实现改变,但数据类型是bytearray
b = bytearray("abcde",encoding="utf-8")
print(b[2]) #98
b[1]=80
print(b,type(b))
#callable 是否可调用, 函数、类是可调用的,即可以加()的
print(callable(s))
#char 用数字转换为ascii码的字符,ord 相反
print(chr(97))
print(ord("b"))
#classmethod 类方法
#print(chr(97))
#complie 变成可执行的代码 的过程
#divmod A/B 返回 商 和 余数
print(divmod(100,33))
#eval 把一个字符串变字典。
#exce 把一个字符变为可执行程序
#匿名函数 lambda 只能写三元运算,不能做更多的判断
calc = lambda n:print(n)
calc1 = lambda n:3 if n<4 else n
calc(5)
print(calc1(1))
#filter 一组数据中过滤出你想要的,配合lambda使用
res = filter(lambda n:n>5,range(10))
for i in res:
print(i)
#map 对传入的值按照函数的方式处理,然后返回
ret = map(lambda n:n**2,range(10))
for j in ret:
print(j)
#frozenset 不可变集合
aa = frozenset([11,22,33,44,33,22,11,55,66])
print(aa)
#globals 返回当前文件中所有变量的k v 格式
print(globals())
#hash
print(hash(aa))
#hex 数字转16进制 oct 数字转8进制
a = {0: 10000, 6: 2, 1: 4, -5: 6, 99: 11, 1111: 32}
print(sorted(a.items())) #按照key排序
print(sorted(a.items(),key = lambda x:x[1])) #按照value排序
#zip 拉链函数 ,以最短的聚合
a=[1,2,3,4]
b=['a','b','c','d','e','f']
for i in zip(a,b):
print(i)
(1, 'a')
(2, 'b')
(3, 'c')
(4, 'd')
__import__('decorator')
json和pickle
info ={'name':'alex','age':22}
# with open('test.txt',"w") as f:
# f.write(str(info))
# with open('test.txt',"r") as f:
# data=eval(f.read())
# print(data)
'''json 序列化和反序列化 json.dumps() json.loads() '''
import json
# with open('test.txt',"w") as f:
# f.write(json.dumps(info))
# with open('test.txt',"r") as f:
# data = json.loads(f.read())
# print(data,type(data))
'''pickle 只能在python中使用,可以对所有数据类型按照bit格式 进行写入和读取操作'''
import pickle
def sayhi(name):
print("Hello",name)
info['func'] = sayhi
# print(info)
# print(pickle.dumps(info))
# with open('test.txt',"wb") as f:
# f.write(pickle.dumps(info))
with open('test.txt',"rb") as f:
data = pickle.loads(f.read())
print(data["func"]('alex'))
import的本质:
''
包:本质就是一个文件夹,区别是必须带有__init__.py文件
导入包的本质是解释包下面的__init__.py文件
模块:
1、定义:模块用来从逻辑上组织python代码(变量、函数、类,逻辑:实现一个功能)
本质上就是以.py结尾的python文件(文件名test.py对应的模块名:test)
2、导入方法
import module_1
import module_1,module_2
from module_1 import * (不使用,容易出现变量等冲突)
from module_1 import m1,m2,m3
from module_1 import logger as logger_m
3、import本质(路径搜索和搜索路径)
把文件解释一遍,import 文件名代表导入所有,from只解释from的那一段,
import module_name ----->module_name.py---->必须找到文件的路径
在sys.path 列出的路径下找
4、导入优化
多次调用 import module 中的test方法时,会造成效率低下,
建议使用 from module import test 或者加上 as module_test_test
5、模块的分类:
a:标准库
b:开源模块
c:自定义模块
'''
#import module_1 = module_1 = all code
#from module_1 import say_hi 把module_1中的say_hi 函数放到当前位置,并命名为 say_hi
import module_1
module_1.say_hi()
from module_1 import say_hi
name1 = "Wu Teng Nuan"
say_hi()
#导入包
import package_test
os模块
import os
print(os.getcwd()) #获取当前工作目录,即当前python脚本工作的目录路径
print(os.chdir("c:\\")) # 改变当前脚本工作目录;相当于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 # 输出用于分割文件路径的字符串
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.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所指向的文件或者目录的最后修改时间
shutil模块
##高级的 文件、文件夹、压缩包 处理模块
import shutil
#shutil.copyfileobj('os-mk.py', 'os-1',100)
#将文件内容拷贝到另一个文件中,可以部分内容
shutil.copyfile("os-mk.py","os-mk")
#拷贝文件
shutil.copymode("os-mk.py","os-mk")
#仅拷贝权限。内容、组、用户均不变 !!! linux 比较适用,windows下看不出来太大区别
shutil.copystat("os-mk.py","os-mk")
#拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copy("os-mk.py", "os-mk1")
#拷贝文件和权限
shutil.copy2("os-mk1","os-m1")
#拷贝文件和状态信息
#shutil.ignore_patterns(*patterns)
#shutil.copytree(src, dst, symlinks=False, ignore=None)
#递归的去拷贝文件,文件夹
#shutil.copytree('py06', 'py05', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
#shutil.rmtree('py05')
#递归的去删除文件
#shutil.move('py06', 'py04')
#递归的去移动文件
'''
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir: 要压缩的文件夹路径(默认当前目录)
owner: 用户,默认当前用户
group: 组,默认当前组
logger: 用于记录日志,通常是logging.Logger对象
'''
shutil.make_archive('aaaa.tar', 'tar')
shelve模块
是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式
import shelve
d = shelve.open('shelve--test') # 打开一个文件
# d["name"] = ["alex", "WutN", "test"]
# d["age"] = 22 # 持久化类
# d['info'] = {"name":"alex","age":21,"school":"Oldboy"}
# d.close()
print(dir(d))
print(d.get("name"))
print(d.get("info"))
logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为 debug()
, info()
, warning()
, error()
and critical() 5个级别,
下面我们看一下怎么用。
最简单用法
import logging
logging.warning("user [alex] attempted wrong password more than 3 times")
logging.critical("server is down")
#输出
WARNING:root:user [alex] attempted wrong password more than 3 times
CRITICAL:root:server is down
看一下这几个日志级别分别代表什么意思
Level | When it’s used |
---|---|
DEBUG | Detailed information, typically of interest only when diagnosing problems. |
INFO | Confirmation that things are working as expected. |
WARNING | An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected. |
ERROR | Due to a more serious problem, the software has not been able to perform some function. |
CRITICAL | A serious error, indicating that the program itself may be unable to continue running. |
如果想把日志写到文件里,也很简单
1
2
3
4
5
6
|
import
logging
logging.basicConfig(filename
=
'example.log'
,level
=
logging.INFO)
logging.debug(
'This message should go to the log file'
)
logging.info(
'So should this'
)
logging.warning(
'And this, too'
)
|
其中下面这句中的level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子, 第一条日志是不会被纪录的,如果希望纪录debug的日志,那把日志级别改成DEBUG就行了。
1
|
logging.basicConfig(filename
=
'example.log'
,level
=
logging.INFO)
|
感觉上面的日志格式忘记加上时间啦,日志不知道时间怎么行呢,下面就来加上!
1
2
3
4
5
6
|
import
logging
logging.basicConfig(
format
=
'%(asctime)s %(message)s'
, datefmt
=
'%m/%d/%Y %I:%M:%S %p'
)
logging.warning(
'is when this event was logged.'
)
#输出
12
/
12
/
2010
11
:
46
:
36
AM
is
when this event was logged.
|
日志格式
%(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 | 用户输出的消息 |
如果想同时把log打印在屏幕和文件日志里,就需要了解一点复杂的知识 了
Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适:
logger提供了应用程序可以直接使用的接口;
handler将(logger创建的)日志记录发送到合适的目的输出;
filter提供了细度设备来决定输出哪条日志记录;
formatter决定日志记录的最终输出格式。
logger
每个程序在输出信息之前都要获得一个Logger。Logger通常对应了程序的模块名,比如聊天工具的图形界面模块可以这样获得它的Logger:
LOG=logging.getLogger(”chat.gui”)
而核心模块可以这样:
LOG=logging.getLogger(”chat.kernel”)
Logger.setLevel(lel):指定最低的日志级别,低于lel的级别将被忽略。debug是最低的内置级别,critical为最高
Logger.addFilter(filt)、Logger.removeFilter(filt):添加或删除指定的filter
Logger.addHandler(hdlr)、Logger.removeHandler(hdlr):增加或删除指定的handler
Logger.debug()、Logger.info()、Logger.warning()、Logger.error()、Logger.critical():可以设置的日志级别
handler
handler对象负责发送相关的信息到指定目的地。Python的日志系统有多种Handler可以使用。有些Handler可以把信息输出到控制台,有些Logger可以把信息输出到文件,还有些 Handler可以把信息发送到网络上。如果觉得不够用,还可以编写自己的Handler。可以通过addHandler()方法添加多个多handler
Handler.setLevel(lel):指定被处理的信息级别,低于lel级别的信息将被忽略
Handler.setFormatter():给这个handler选择一个格式
Handler.addFilter(filt)、Handler.removeFilter(filt):新增或删除一个filter对象
每个Logger可以附加多个Handler。接下来我们就来介绍一些常用的Handler:
1) logging.StreamHandler
使用这个Handler可以向类似与sys.stdout或者sys.stderr的任何文件对象(file object)输出信息。它的构造函数是:
StreamHandler([strm])
其中strm参数是一个文件对象。默认是sys.stderr
2) logging.FileHandler
和StreamHandler类似,用于向一个文件输出日志信息。不过FileHandler会帮你打开这个文件。它的构造函数是:
FileHandler(filename[,mode])
filename是文件名,必须指定一个文件名。
mode是文件的打开方式。参见Python内置函数open()的用法。默认是’a',即添加到文件末尾。
3) logging.handlers.RotatingFileHandler
这个Handler类似于上面的FileHandler,但是它可以管理文件大小。当文件达到一定大小之后,它会自动将当前日志文件改名,然后创建 一个新的同名日志文件继续输出。比如日志文件是chat.log。当chat.log达到指定的大小之后,RotatingFileHandler自动把 文件改名为chat.log.1。不过,如果chat.log.1已经存在,会先把chat.log.1重命名为chat.log.2。。。最后重新创建 chat.log,继续输出日志信息。它的构造函数是:
RotatingFileHandler( filename[, mode[, maxBytes[, backupCount]]])
其中filename和mode两个参数和FileHandler一样。
maxBytes用于指定日志文件的最大文件大小。如果maxBytes为0,意味着日志文件可以无限大,这时上面描述的重命名过程就不会发生。
backupCount用于指定保留的备份文件的个数。比如,如果指定为2,当上面描述的重命名过程发生时,原有的chat.log.2并不会被更名,而是被删除。
4) logging.handlers.TimedRotatingFileHandler
这个Handler和RotatingFileHandler类似,不过,它没有通过判断文件大小来决定何时重新创建日志文件,而是间隔一定时间就 自动创建新的日志文件。重命名的过程与RotatingFileHandler类似,不过新的文件不是附加数字,而是当前时间。它的构造函数是:
TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])
其中filename参数和backupCount参数和RotatingFileHandler具有相同的意义。
interval是时间间隔。
when参数是一个字符串。表示时间间隔的单位,不区分大小写。它有以下取值:
S 秒
M 分
H 小时
D 天
W 每星期(interval==0时代表星期一)
midnight 每天凌晨
re模块:::
常用正则表达式符号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
'.'
默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
'^'
匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r
"^a"
,
"\nabc\neee"
,flags
=
re.MULTILINE)
'$'
匹配字符结尾,或e.search(
"foo$"
,
"bfoo\nsdfsf"
,flags
=
re.MULTILINE).group()也可以
'*'
匹配
*
号前的字符
0
次或多次,re.findall(
"ab*"
,
"cabb3abcbbac"
) 结果为[
'abb'
,
'ab'
,
'a'
]
'+'
匹配前一个字符
1
次或多次,re.findall(
"ab+"
,
"ab+cd+abb+bba"
) 结果[
'ab'
,
'abb'
]
'?'
匹配前一个字符
1
次或
0
次
'{m}'
匹配前一个字符m次
'{n,m}'
匹配前一个字符n到m次,re.findall(
"ab{1,3}"
,
"abb abc abbcbbb"
) 结果
'abb'
,
'ab'
,
'abb'
]
'|'
匹配|左或|右的字符,re.search(
"abc|ABC"
,
"ABCBabcCD"
).group() 结果
'ABC'
'(...)'
分组匹配,re.search(
"(abc){2}a(123|456)c"
,
"abcabca456c"
).group() 结果 abcabca456c
'\A'
只从字符开头匹配,re.search(
"\Aabc"
,
"alexabc"
) 是匹配不到的
'\Z'
匹配字符结尾,同$
'\d'
匹配数字
0
-
9
'\D'
匹配非数字
'\w'
匹配[A
-
Za
-
z0
-
9
]
'\W'
匹配非[A
-
Za
-
z0
-
9
]
's'
匹配空白字符、\t、\n、\r , re.search(
"\s+"
,
"ab\tc1\n3"
).group() 结果
'\t'
'(?P<name>...)'
分组匹配 re.search(
"(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})"
,
"371481199306143242"
).groupdict(
"city"
) 结果{
'province'
:
'3714'
,
'city'
:
'81'
,
'birthday'
:
'1993'
}
|
最常用的匹配语法
1
2
3
4
5
|
re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
|
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
仅需轻轻知道的几个匹配模式
1
2
3
|
re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变
'^'
和
'$'
的行为(参见上图)
S(DOTALL): 点任意匹配模式,改变
'.'
的行为
|
import re
#re.match 匹配是否以字符开始 没有匹配上返回None,此时不具有group属性,会报错。
#re.serch 全文搜索
#re.findall 搜索所有的
#re.split 以匹配到的进行分割
#re.sub() 以第二个来替换匹配到的信息 re.sub(search,repl,string,count=)
a = re.match("\w*",'inter 192.168.0.161')
print(a,a.group())
# group 和groups的却别, groups 打印出分组()中匹配到的数据
b = re.match('(\d{2})(\d{2})(\d{2})(\d{4})','212312200212172233 name:alex')
print(b.group())
print(b.groups())
print(re.search('^\d.*\d\Z','213123124xyz1432432').group())
# ?P<内容> 搭配groupdict(),转为字典格式,装逼ing
cc = re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<year>[0-9]{4})","212312200212172233")
print(cc.groups())
print(cc.group())
print(cc.groupdict())
print(re.findall('\w','a!!!!c@@ww$$$$'))
print(re.split('\d+','ads1ljkk132kjh43h234jhj24k3hj234jkh66'))
print(re.sub('\d+','||','ads1ljkk132kjh43h234jhj24k3hj234jkh66'))
# 自然语言,不对字符串进行转移 logs'string'
print(re.split('\\\\',logs'c:\\user\pwd\new\python33'))
print(re.split(logs'\\',logs'c:\\user\pwd\new\python33'))
#flags re.I 忽略大小写 re.M 多行模式 re.
print(re.search('a','ABC',flags=re.I))
print(re.search('^A.*\w$','ABCabcdsfs4\n213789sdff', flags=re.M).group())
#re.match 匹配是否以字符开始 没有匹配上返回None,此时不具有group属性,会报错。
#re.serch 全文搜索
#re.findall 搜索所有的
#re.split 以匹配到的进行分割
#re.sub() 以第二个来替换匹配到的信息 re.sub(search,repl,string,count=)
a = re.match("\w*",'inter 192.168.0.161')
print(a,a.group())
# group 和groups的却别, groups 打印出分组()中匹配到的数据
b = re.match('(\d{2})(\d{2})(\d{2})(\d{4})','212312200212172233 name:alex')
print(b.group())
print(b.groups())
print(re.search('^\d.*\d\Z','213123124xyz1432432').group())
# ?P<内容> 搭配groupdict(),转为字典格式,装逼ing
cc = re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<year>[0-9]{4})","212312200212172233")
print(cc.groups())
print(cc.group())
print(cc.groupdict())
print(re.findall('\w','a!!!!c@@ww$$$$'))
print(re.split('\d+','ads1ljkk132kjh43h234jhj24k3hj234jkh66'))
print(re.sub('\d+','||','ads1ljkk132kjh43h234jhj24k3hj234jkh66'))
# 自然语言,不对字符串进行转移 logs'string'
print(re.split('\\\\',logs'c:\\user\pwd\new\python33'))
print(re.split(logs'\\',logs'c:\\user\pwd\new\python33'))
#flags re.I 忽略大小写 re.M 多行模式 re.
print(re.search('a','ABC',flags=re.I))
print(re.search('^A.*\w$','ABCabcdsfs4\n213789sdff', flags=re.M).group())
print(re.search('.+','ABC\n2137\n89sdff', flags=re.S).group())