Python20-Day05
一、模块与包
1、模块
什么是模块?
在python中,模块可以分为四个通用类别:
1. 使用python编写的.py文件
2. 已经被编译为共享库或DLL的c或者c++扩展
3. 把一系列模块组织到一起的文件夹(注:文件夹下面有一个__init__.py文件,该文件夹称为包)
4. 使用c编写并链接到python解释器的内置模块!
为什么要使用模块?
1、从文件级别组织程序,更方便管理
2、拿来主义,提升开发效率
以spam.py为例,来介绍模块的使用:文件名为spam.py 模块名:spam
- #spam.py
- print('from the spam.py')
- money=1000
- def read1():
- print('spam模块:',money)
- def read2():
- print('spam模块')
- read1()
- def change():
- global money
- money=0
2、使用模块之import
import的使用
模块可以包含可执行的语句和函数的定义,为了初始化模块,只在模块名第一次遇到导入import语句时才执行。import语句是可以在程序中的任意位置使用的,且针对同一个模块可以import多次,为了防止重复导入,优化手段是:第一次导入就将模块名加载到内存中了,后续的import语句只是对已经加载到内存中的模块对象增加了一次引用,不会重复执行模块内的语句。
- #test.py
- import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次'from the spam.py',当然其他的顶级代码也都被执行了,只不过没有显示效果.
- import spam
- import spam
- import spam
- '''
- 执行结果:
- from the spam.py
- '''
注:可以从sys.module中找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
在第一次导入模块时,会做三件事,重复导入会直接引用内存中已经加载好的结果
1、 为源文件(spam模块)创建新的名称空间,在spam中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
2、在新创建的命名空间中执行模块中包含的代码,见初始导入import spam;函数定义也是被执行的语句,模块级别函数定义的执行将函数名放入模块全局名称空间,用globals()可以查看。
3、创建名字spam来引用改命名空间。
被导入的名称有独立的名称空间
每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样在编写自己的模块时,就不用担心定义在自己模块中的全局变量会在被导入时,与使用者的全局变量冲突。
为模块起别名:
import spam as sm
在一行中导入多个模块
from spam import read1,read2
3、使用模块之from ... import ...
4、模块搜索路径
- #模块的查找顺序
- 1、在第一次导入某个模块时(比如spam),会先检查该模块是否已经被加载到内存中(当前执行文件的名称空间对应的内存),如果有则直接引用
- ps:python解释器在启动时会自动加载一些模块到内存中,可以使用sys.modules查看
- 2、如果没有,解释器则会查找同名的内建模块
- 3、如果还没有找到就从sys.path给出的目录列表中依次寻找spam.py文件。
- #sys.path的初始化的值来自于:
- The directory containing the input script (or the current directory when no file is specified).
- PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
- The installation-dependent default.
- #需要特别注意的是:我们自定义的模块名不应该与系统内置模块重名。虽然每次都说,但是仍然会有人不停的犯错。
- #在初始化后,python程序可以修改sys.path,路径放到前面的优先于标准库被加载。
- >>> import sys
- >>> sys.path.append('/a/b/c/d')
- >>> sys.path.insert(0,'/x/y/z') #排在前的目录,优先被搜索
- 注意:搜索时按照sys.path中从左到右的顺序查找,位于前的优先被查找,sys.path中还可能包含.zip归档文件和.egg文件,python会把.zip归档文件当成一个目录去处理,
- #首先制作归档文件:zip module.zip foo.py bar.py
- import sys
- sys.path.append('module.zip')
- import foo,bar
- #也可以使用zip中目录结构的具体位置
- sys.path.append('module.zip/lib/python')
- #windows下的路径不加r开头,会语法错误
- sys.path.insert(0,r'C:\Users\Administrator\PycharmProjects\a')
- #至于.egg文件是由setuptools创建的包,这是按照第三方python库和扩展时使用的一种常见格式,.egg文件实际上只是添加了额外元数据(如版本号,依赖项等)的.zip文件。
- #需要强调的一点是:只能从.zip文件中导入.py,.pyc等文件。使用C编写的共享库和扩展块无法直接从.zip文件中加载(此时setuptools等打包系统有时能提供一种规避方法),且从.zip中加载文件不会创建.pyc或者.pyo文件,因此一定要事先创建他们,来避免加载模块是性能下降。
5、包介绍
什么是包?
- 1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
- 2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包的本质就是一种模块
为什么要使用包?
- 包的本质就是一个文件夹,那么文件夹唯一的功能就是将文件组织起来
- 随着功能越写越多,我们无法将所以功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们就需要用文件夹将模块文件组织起来,以此来提高程序的结构性和可维护性
6、 包的使用
1、示范文件
- glance/ #Top-level package
- ├── __init__.py #Initialize the glance package
- ├── api #Subpackage for api
- │ ├── __init__.py
- │ ├── policy.py
- │ └── versions.py
- ├── cmd #Subpackage for cmd
- │ ├── __init__.py
- │ └── manage.py
- └── db #Subpackage for db
- ├── __init__.py
- └── models.py
- #文件内容
- #policy.py
- def get():
- print('from policy.py')
- #versions.py
- def create_resource(conf):
- print('from version.py: ',conf)
- #manage.py
- def main():
- print('from manage.py')
- #models.py
- def register_models(engine):
- print('from models.py: ',engine)
执行文件与示范文件在同级目录下
2、包的使用之import
- 1 import glance.db.models
- 2 glance.db.models.register_models('mysql')
- 单独导入包名称时不会导入包中所有包含的所有子模块,如
- #在与glance同级的test.py中
- import glance
- glance.cmd.manage.main()
- '''
- 执行结果:
- AttributeError: module 'glance' has no attribute 'cmd'
- '''
解决方法:
- 1 #glance/__init__.py
- 2 from . import cmd
- 3
- 4 #glance/cmd/__init__.py
- 5 from . import manage
- 执行:
- 1 #在于glance同级的test.py中
- 2 import glance
- 3 glance.cmd.manage.main()
- 3、包的使用之from ... import ..
需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
- 1 from glance.db import models
- 2 models.register_models('mysql')
- 3
- 4 from glance.db.models import register_models
- 5 register_models('mysql')
- 4、from glance.api import *
在讲模块时,我们已经讨论过了从一个模块内导入所有*,此处我们研究从一个包导入所有*。
此处是想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:
- 1 #在__init__.py中定义
- 2 x=10
- 3
- 4 def func():
- 5 print('from api.__init.py')
- 6
- 7 __all__=['x','func','policy']
此时我们在于glance同级的文件中执行from glance.api import *就导入__all__中的内容(versions仍然不能导入)。
- #执行文件中的使用效果如下,请处理好包的导入
- from glance import *
- get()
- create_resource('a.conf')
- main()
- register_models('mysql')
5、绝对导入和相对导入
我们的最顶级包glance是写给别人用的,然后在glance包内部也会有彼此之间互相导入的需求,这时候就有绝对导入和相对导入两种方式:
绝对导入:以glance作为起始
相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)
例如:我们在glance/api/version.py中想要导入glance/cmd/manage.py
- 1 在glance/api/version.py
- 2
- 3 #绝对导入
- 4 from glance.cmd import manage
- 5 manage.main()
- 6
- 7 #相对导入
- 8 from ..cmd import manage
- 9 manage.main()
测试结果:注意一定要在于glance同级的文件中测试
1 from glance.api import versions
6、包以及包所包含的模块都是用来被导入的,而不是被直接执行的。而环境变量都是以执行文件为准的
比如我们想在glance/api/versions.py中导入glance/api/policy.py,有的同学一抽这俩模块是在同一个目录下,十分开心的就去做了,它直接这么做
- 1 #在version.py中
- 2
- 3 import policy
- 4 policy.get()
没错,我们单独运行version.py是一点问题没有的,运行version.py的路径搜索就是从当前路径开始的,于是在导入policy时能在当前目录下找到
但是你想啊,你子包中的模块version.py极有可能是被一个glance包同一级别的其他文件导入,比如我们在于glance同级下的一个test.py文件中导入version.py,如下
- 1 from glance.api import versions
- 2
- 3 '''
- 4 执行结果:
- 5 ImportError: No module named 'policy'
- 6 '''
- 7
- 8 '''
- 9 分析:
- 10 此时我们导入versions在versions.py中执行
- 11 import policy需要找从sys.path也就是从当前目录找policy.py,
- 12 这必然是找不到的
- 13 '''
二、常用模块
logging模块
日志级别
- CRITICAL = 50 #FATAL = CRITICAL
- ERROR = 40
- WARNING = 30 #WARN = WARNING
- INFO = 20
- DEBUG = 10
- NOTSET = 0 #不设置
默认级别为warning,默认打印到终端
- import logging
- logging.debug('调试debug')
- logging.info('消息info')
- logging.warning('警告warn')
- logging.error('错误error')
- logging.critical('严重critical')
- '''
- WARNING:root:警告warn
- ERROR:root:错误error
- CRITICAL:root:严重critical
- '''
为logging模块指定全局配置,针对所有logger有效,控制打印到文件中
- 复制代码
- 可在logging.basicConfig()函数中通过具体参数来更改logging模块默认行为,可用参数有
- filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
- filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
- format:指定handler使用的日志显示格式。
- datefmt:指定日期时间格式。
- level:设置rootlogger(后边会讲解具体概念)的日志级别
- stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为sys.stderr。若同时列出了filename和stream两个参数,则stream参数会被忽略。
- #格式
- %(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:用户输出的消息
- #======介绍
- 可在logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有
- filename:用指定的文件名创建FiledHandler(后边会具体讲解handler的概念),这样日志会被存储在指定的文件中。
- filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
- format:指定handler使用的日志显示格式。
- datefmt:指定日期时间格式。
- level:设置rootlogger(后边会讲解具体概念)的日志级别
- stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件,默认为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
- logging.basicConfig(filename='access.log',
- format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
- datefmt='%Y-%m-%d %H:%M:%S %p',
- level=10)
- logging.debug('调试debug')
- logging.info('消息info')
- logging.warning('警告warn')
- logging.error('错误error')
- logging.critical('严重critical')
- #========结果
- access.log内容:
- 2017-07-28 20:32:17 PM - root - DEBUG -test: 调试debug
- 2017-07-28 20:32:17 PM - root - INFO -test: 消息info
- 2017-07-28 20:32:17 PM - root - WARNING -test: 警告warn
- 2017-07-28 20:32:17 PM - root - ERROR -test: 错误error
- 2017-07-28 20:32:17 PM - root - CRITICAL -test: 严重critical
- part2: 可以为logging模块指定模块级的配置,即所有logger的配置
4、logging模块的Formatter,Handler,Logger,Filter对象
- #logger:产生日志的对象
- #Filter:过滤日志的对象
- #Handler:接收日志然后控制打印到不同的地方,FileHandler用来打印到文件中,StreamHandler用来打印到终端
- #Formatter对象:可以定制不同的日志格式对象,然后绑定给不同的Handler对象使用,以此来控制不同的Handler的日志格式
- '''
- critical=50
- error =40
- warning =30
- info = 20
- debug =10
- '''
- import logging
- #1、logger对象:负责产生日志,然后交给Filter过滤,然后交给不同的Handler输出
- logger=logging.getLogger(__file__)
- #2、Filter对象:不常用,略
- #3、Handler对象:接收logger传来的日志,然后控制输出
- h1=logging.FileHandler('t1.log') #打印到文件
- h2=logging.FileHandler('t2.log') #打印到文件
- h3=logging.StreamHandler() #打印到终端
- #4、Formatter对象:日志格式
- formmater1=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
- datefmt='%Y-%m-%d %H:%M:%S %p',)
- formmater2=logging.Formatter('%(asctime)s : %(message)s',
- datefmt='%Y-%m-%d %H:%M:%S %p',)
- formmater3=logging.Formatter('%(name)s %(message)s',)
- #5、为Handler对象绑定格式
- h1.setFormatter(formmater1)
- h2.setFormatter(formmater2)
- h3.setFormatter(formmater3)
- #6、将Handler添加给logger并设置日志级别
- logger.addHandler(h1)
- logger.addHandler(h2)
- logger.addHandler(h3)
- logger.setLevel(10)
- #7、测试
- logger.debug('debug')
- logger.info('info')
- logger.warning('warning')
- logger.error('error')
- logger.critical('critical')
5、Logger与Handler的级别
logger是第一级过滤,然后才能到handler,可以设置level
- Logger is also the first to filter the message based on a level — if you set the logger to INFO, and all handlers to DEBUG, you still won't receive DEBUG messages on handlers — they'll be rejected by the logger itself. If you set logger to DEBUG, but all handlers to INFO, you won't receive any DEBUG messages either — because while the logger says "ok, process this", the handlers reject it (DEBUG < INFO).
- #验证
- import logging
- form=logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
- datefmt='%Y-%m-%d %H:%M:%S %p',)
- ch=logging.StreamHandler()
- ch.setFormatter(form)
- # ch.setLevel(10)
- ch.setLevel(20)
- l1=logging.getLogger('root')
- # l1.setLevel(20)
- l1.setLevel(10)
- l1.addHandler(ch)
- l1.debug('l1 debug')
7.应用
- """
- logging配置
- """
- import os
- import logging.config
- # 定义三种日志输出格式 开始
- standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
- '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字
- simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'
- id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'
- # 定义日志输出格式 结束
- logfile_dir = os.path.dirname(os.path.abspath(__file__)) # log文件的目录
- logfile_name = 'all2.log' # log文件名
- # 如果不存在定义的日志目录就创建一个
- if not os.path.isdir(logfile_dir):
- os.mkdir(logfile_dir)
- # log文件的全路径
- logfile_path = os.path.join(logfile_dir, logfile_name)
- # log配置字典
- LOGGING_DIC = {
- 'version': 1,
- 'disable_existing_loggers': False,
- 'formatters': {
- 'standard': {
- 'format': standard_format
- },
- 'simple': {
- 'format': simple_format
- },
- },
- 'filters': {},
- 'handlers': {
- #打印到终端的日志
- 'console': {
- 'level': 'DEBUG',
- 'class': 'logging.StreamHandler', # 打印到屏幕
- 'formatter': 'simple'
- },
- #打印到文件的日志,收集info及以上的日志
- 'default': {
- 'level': 'DEBUG',
- 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
- 'formatter': 'standard',
- 'filename': logfile_path, # 日志文件
- 'maxBytes': 1024*1024*5, # 日志大小 5M
- 'backupCount': 5,
- 'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
- },
- },
- 'loggers': {
- #logging.getLogger(__name__)拿到的logger配置
- '': {
- 'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
- 'level': 'DEBUG',
- 'propagate': True, # 向上(更高level的logger)传递
- },
- },
- }
- def load_my_logging_cfg():
- logging.config.dictConfig(LOGGING_DIC) # 导入上面定义的logging配置
- logger = logging.getLogger(__name__) # 生成一个log实例
- logger.info('It works!') # 记录该文件的运行状态
- if __name__ == '__main__':
- load_my_logging_cfg()
- """
- MyLogging Test
- """
- import time
- import logging
- import my_logging # 导入自定义的logging配置
- logger = logging.getLogger(__name__) # 生成logger实例
- def demo():
- logger.debug("start range... time:{}".format(time.time()))
- logger.info("中文测试开始。。。")
- for i in range(10):
- logger.debug("i:{}".format(i))
- time.sleep(0.2)
- else:
- logger.debug("over range... time:{}".format(time.time()))
- logger.info("中文测试结束。。。")
- if __name__ == "__main__":
- my_logging.load_my_logging_cfg() # 在你程序文件的入口加载自定义logging配置
- demo()
- #1、有了上述方式我们的好处是:所有与logging模块有关的配置都写到字典中就可以了,更加清晰,方便管理
- #2、我们需要解决的问题是:
- 1、从字典加载配置:logging.config.dictConfig(settings.LOGGING_DIC)
- 2、拿到logger对象来产生日志
- logger对象都是配置到字典的loggers 键对应的子字典中的
- 按照我们对logging模块的理解,要想获取某个东西都是通过名字,也就是key来获取的
- 于是我们要获取不同的logger对象就是
- logger=logging.getLogger('loggers子字典的key名')
- 但问题是:如果我们想要不同logger名的logger对象都共用一段配置,那么肯定不能在loggers子字典中定义n个key
- 'loggers': {
- 'l1': {
- 'handlers': ['default', 'console'], #
- 'level': 'DEBUG',
- 'propagate': True, # 向上(更高level的logger)传递
- },
- 'l2: {
- 'handlers': ['default', 'console' ],
- 'level': 'DEBUG',
- 'propagate': False, # 向上(更高level的logger)传递
- },
- 'l3': {
- 'handlers': ['default', 'console'], #
- 'level': 'DEBUG',
- 'propagate': True, # 向上(更高level的logger)传递
- },
- }
- #我们的解决方式是,定义一个空的key
- 'loggers': {
- '': {
- 'handlers': ['default', 'console'],
- 'level': 'DEBUG',
- 'propagate': True,
- },
- }
- 这样我们再取logger对象时
- logging.getLogger(__name__),不同的文件__name__不同,这保证了打印日志时标识信息不同,但是拿着该名字去loggers里找key名时却发现找不到,于是默认使用key=''的配置
re模块
http://blog.csdn.net/yufenghyc/article/details/51078107
- # =================================匹配模式=================================
- #一对一的匹配
- # 'hello'.replace(old,new)
- # 'hello'.find('pattern')
- #正则匹配
- import re
- #\w与\W
- print(re.findall('\w','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']
- print(re.findall('\W','hello egon 123')) #[' ', ' ']
- #\s与\S
- print(re.findall('\s','hello egon 123')) #[' ', ' ', ' ', ' ']
- print(re.findall('\S','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']
- #\n \t都是空,都可以被\s匹配
- print(re.findall('\s','hello \n egon \t 123')) #[' ', '\n', ' ', ' ', '\t', ' ']
- #\n与\t
- print(re.findall(r'\n','hello egon \n123')) #['\n']
- print(re.findall(r'\t','hello egon\t123')) #['\n']
- #\d与\D
- print(re.findall('\d','hello egon 123')) #['1', '2', '3']
- print(re.findall('\D','hello egon 123')) #['h', 'e', 'l', 'l', 'o', ' ', 'e', 'g', 'o', 'n', ' ']
- #\A与\Z
- print(re.findall('\Ahe','hello egon 123')) #['he'],\A==>^
- print(re.findall('123\Z','hello egon 123')) #['he'],\Z==>$
- #^与$
- print(re.findall('^h','hello egon 123')) #['h']
- print(re.findall('3$','hello egon 123')) #['3']
- # 重复匹配:| . | * | ? | .* | .*? | + | {n,m} |
- #.
- print(re.findall('a.b','a1b')) #['a1b']
- print(re.findall('a.b','a1b a*b a b aaab')) #['a1b', 'a*b', 'a b', 'aab']
- print(re.findall('a.b','a\nb')) #[]
- print(re.findall('a.b','a\nb',re.S)) #['a\nb']
- print(re.findall('a.b','a\nb',re.DOTALL)) #['a\nb']同上一条意思一样
- #*
- print(re.findall('ab*','bbbbbbb')) #[]
- print(re.findall('ab*','a')) #['a']
- print(re.findall('ab*','abbbb')) #['abbbb']
- #?
- print(re.findall('ab?','a')) #['a']
- print(re.findall('ab?','abbb')) #['ab']
- #匹配所有包含小数在内的数字
- print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3']
- #.*默认为贪婪匹配
- print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b']
- #.*?为非贪婪匹配:推荐使用
- print(re.findall('a.*?b','a1b22222222b')) #['a1b']
- #+
- print(re.findall('ab+','a')) #[]
- print(re.findall('ab+','abbb')) #['abbb']
- #{n,m}
- print(re.findall('ab{2}','abbb')) #['abb']
- print(re.findall('ab{2,4}','abbb')) #['abb']
- print(re.findall('ab{1,}','abbb')) #'ab{1,}' ===> 'ab+'
- print(re.findall('ab{0,}','abbb')) #'ab{0,}' ===> 'ab*'
- #[]
- print(re.findall('a[1*-]b','a1b a*b a-b')) #[]内的都为普通字符了,且如果-没有被转意的话,应该放到[]的开头或结尾
- print(re.findall('a[^1*-]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']
- print(re.findall('a[0-9]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']
- print(re.findall('a[a-z]b','a1b a*b a-b a=b aeb')) #[]内的^代表的意思是取反,所以结果为['a=b']
- print(re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb')) #[]内的^代表的意思是取反,所以结果为['a=b']
- #\# print(re.findall('a\\c','a\c')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常
- print(re.findall(r'a\\c','a\c')) #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义
- print(re.findall('a\\\\c','a\c')) #同上面的意思一样,和上面的结果一样都是['a\\c']
- #():分组
- print(re.findall('ab+','ababab123')) #['ab', 'ab', 'ab']
- print(re.findall('(ab)+123','ababab123')) #['ab'],匹配到末尾的ab123中的ab
- print(re.findall('(?:ab)+123','ababab123')) #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容
- print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">点击</a>'))#['http://www.baidu.com']
- print(re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">点击</a>'))#['href="http://www.baidu.com"']
- #|
- print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company'))
- # ===========================re模块提供的方法介绍===========================
- import re
- #
- print(re.findall('e','alex make love') ) #['e', 'e', 'e'],返回所有满足匹配条件的结果,放在列表里
- #
- print(re.search('e','alex make love').group()) #e,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
- #
- print(re.match('e','alex make love')) #None,同search,不过在字符串开始处进行匹配,完全可以用search+^代替match
- #
- print(re.split('[ab]','abcd')) #['', '', 'cd'],先按'a'分割得到''和'bcd',再对''和'bcd'分别按'b'分割
- #
- print('===>',re.sub('a','A','alex make love')) #===> Alex mAke love,不指定n,默认替换所有
- print('===>',re.sub('a','A','alex make love',1)) #===> Alex make love
- print('===>',re.sub('a','A','alex make love',2)) #===> Alex mAke love
- print('===>',re.sub('^(\w+)(.*?\s)(\w+)(.*?\s)(\w+)(.*?)$',r'\5\2\3\4\1','alex make love')) #===> love make alex
- print('===>',re.subn('a','A','alex make love')) #===> ('Alex mAke love', 2),结果带有总共替换的个数
- #
- obj=re.compile('\d{2}')
- print(obj.search('abc123eeee').group()) #
- print(obj.findall('abc123eeee')) #['12'],重用了obj
- import re
- print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")) #['h1']
- print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").group()) #<h1>hello</h1>
- print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").groupdict()) #<h1>hello</h1>
- print(re.search(r"<(\w+)>\w+</(\w+)>","<h1>hello</h1>").group())
- print(re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>").group())
- import re
- print(re.findall(r'-?\d+\.?\d*',"1-12*(60+(-40.35/5)-(-4*3))")) #找出所有数字['1', '-12', '60', '-40.35', '5', '-4', '3']
- #使用|,先匹配的先生效,|左边是匹配小数,而findall最终结果是查看分组,所有即使匹配成功小数也不会存入结果
- #而不是小数时,就去匹配(-?\d+),匹配到的自然就是,非小数的数,在此处即整数
- print(re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")) #找出所有整数['1', '-2', '60', '', '5', '-4', '3']
Python20-Day05的更多相关文章
- My way to Python - Day05 - 面向对象-思维导图
My way to Python - Day05 - 面向对象 思维导图
- day05 Servlet 开发和 ServletConfig 与 ServletContext 对象
day05 Servlet 开发和 ServletConfig 与 ServletContext 对象 1. Servlet 开发入门 - hello world 2. Servlet 的调用过程和生 ...
- python day05笔记总结
2019.4.2 S21 day05笔记总结 一.昨日内容回顾与补充 1.extend(列表独有功能) 循环添加到一个列表中 a.有列表users = ['张三',‘李四] people = [' ...
- Python基础(协程函数、内置函数、递归、模块和包)-day05
写在前面 上课第五天,打卡: 凭着爱,再回首: 一.协程函数(生成器:yield的表达式形式) 1.yield 的语句形式: yield 1 - 这种方式在 Python基础(函数部分)-day04 ...
- day05(Object,tostring(),equals(),System,Date,SimpleDateFormat,拆装箱,正则表达式)
Object类, 是所应类的父类: 拥有自己的方法:常用的 红颜色标记的为常用的方法 toString() 用法:打印对象的地址值 getClass() 获取当前类的字节码文件getName() ...
- 超全面的JavaWeb笔记day05<xml&dtd&jaxp>
0.表单提交方式(*****) button提交 超链接提交 事件 1.xml简介和应用(了解) 2.xml文档声明和乱码解决(*****) 文档声明 必须放在第一行第一列 设置xml编码和保存编码一 ...
- Day05 xml详解
day05总结 今日内容 XML语法 XML约束之DTD XML解析器介绍 XML解析之JAXP( DOM.SAX ) DOM4J Schema 一.XML语法 XML概述 1 什么是XML ...
- day05 --class --home
# -*- coding: utf-8 -*-# @Time : 2018/12/25 14:24# @Author : Endless-cloud# @Site : # @File : day05 ...
- python开发学习-day05(正则深入、冒泡排序算法、自定义模块、常用标准模块)
s12-20160130-day05 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...
- 2017-2018-1 JAVA实验站 冲刺 day05
2017-2018-1 JAVA实验站 冲刺 day05 各个成员今日完成的任务 小组成员 今日工作 完成进度 张韵琪 进行工作总结 100% 齐力锋 找按钮音乐 100% 张浩林 写博客 100% ...
随机推荐
- SSM框架之RestFul示例
演示环境:maven+Spring+SpringMVC+MyBatis Plus或MyBatis都行+JDK8 JDK7我想应该没有问题,原因是用的基本都是JDK6或者JDK7的相关特性. 当然了,J ...
- IFsvnadmin svn界面管理工具
安装部署if.svnadmin 工具 前提是安装好svn服务器及apache+php服务器. yum -y install subversion mod_dav_svn 安装完建立一个目录用来作为sv ...
- 文件上传 python
def upload(): r = requests.post( url='http://upload.renren.com/upload.fcgi?pagetype=addpublishersing ...
- ZOJ3202-Second-price Auction(根据输入输出判断是队列还是栈)
A Stack or A Queue? Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu S ...
- 【CSS3】特殊的属性归纳(一)
CSS3手册地址速查表 -webkit- 最终要用兼容性写法 (一)-webkit-tap-highlight-color (mobile移动设备私有属性) 案列: 问题:遇到a链接和butto ...
- Java-数组队列
Java-数组队列 1.为何要创建一个数组队列? 数组的优点和缺点: 优点:访问速度是所有数据结构中最快的一种. 缺点:大小固定,如果要存储的数据个数不确定的时候? 数组空间不够,导致越界异 ...
- GoogleTest初探(1)
此篇主要了解一下GoogleTest中的断言. 总的来说,GoogleTest中的断言分为两大类:EXPECT_*和ASSERT_*,这两者在测试成功或失败后均会给出测试报告,区别是前者在测试失败后会 ...
- hbase-列存储动态数据库
1) HBase是什么? HBase是建立在Hadoop文件系统之上的分布式面向列的数据库.它是一个开源项目,是横向扩展的. HBase是一个数据模型,类似于谷歌的大表设计,可以提供快速随机访问海 ...
- Kafka基础认识
1):Apache kafka介绍及架构详解 假设一个场景: 数据源: 应用系统A 产生的用户访问数据和订单数据 10000 条一秒钟 push:推送数据 消息系统:队列 产生的数据量>数据量 ...
- 大数据入门第八天——MapReduce详解(四)本地模式运行与join实例
一.本地模式调试MR程序 1.准备 参考之前随笔的windows开发说明处:http://www.cnblogs.com/jiangbei/p/8366238.html 2.流程 最重要的是设置Loc ...