Python20-Day05
一、模塊與包
1、模塊
什么是模塊?
在python中,模塊可以分為四個通用類別:
1. 使用python編寫的.py文件
2. 已經(jīng)被編譯為共享庫或DLL的c或者c++擴(kuò)展
3. 把一系列模塊組織到一起的文件夾(注:文件夾下面有一個__init__.py文件,該文件夾稱為包)
4. 使用c編寫并鏈接到python解釋器的內(nèi)置模塊!
? 為什么要使用模塊?
1、從文件級別組織程序,更方便管理
2、拿來主義,提升開發(fā)效率
以spam.py為例,來介紹模塊的使用:文件名為spam.py? 模塊名:spam
#spam.py print('from the spam.py')money=1000def read1():print('spam模塊:',money)def read2():print('spam模塊')read1()def change():global moneymoney=0
2、使用模塊之import
import的使用
模塊可以包含可執(zhí)行的語句和函數(shù)的定義,為了初始化模塊,只在模塊名第一次遇到導(dǎo)入import語句時才執(zhí)行。import語句是可以在程序中的任意位置使用的,且針對同一個模塊可以import多次,為了防止重復(fù)導(dǎo)入,優(yōu)化手段是:第一次導(dǎo)入就將模塊名加載到內(nèi)存中了,后續(xù)的import語句只是對已經(jīng)加載到內(nèi)存中的模塊對象增加了一次引用,不會重復(fù)執(zhí)行模塊內(nèi)的語句。
#test.py import spam #只在第一次導(dǎo)入時才執(zhí)行spam.py內(nèi)代碼,此處的顯式效果是只打印一次'from the spam.py',當(dāng)然其他的頂級代碼也都被執(zhí)行了,只不過沒有顯示效果. import spam import spam import spam''' 執(zhí)行結(jié)果: from the spam.py '''
?
注:可以從sys.module中找到當(dāng)前已經(jīng)加載的模塊,sys.module是一個字典,內(nèi)部包含模塊名與模塊對象的映射,該字典決定了導(dǎo)入模塊時是否需要重新導(dǎo)入。?
在第一次導(dǎo)入模塊時,會做三件事,重復(fù)導(dǎo)入會直接引用內(nèi)存中已經(jīng)加載好的結(jié)果
1、 為源文件(spam模塊)創(chuàng)建新的名稱空間,在spam中定義的函數(shù)和方法若是使用到了global時訪問的就是這個名稱空間。
2、在新創(chuàng)建的命名空間中執(zhí)行模塊中包含的代碼,見初始導(dǎo)入import spam;函數(shù)定義也是被執(zhí)行的語句,模塊級別函數(shù)定義的執(zhí)行將函數(shù)名放入模塊全局名稱空間,用globals()可以查看。
3、創(chuàng)建名字spam來引用改命名空間。
被導(dǎo)入的名稱有獨(dú)立的名稱空間
每個模塊都是一個獨(dú)立的名稱空間,定義在這個模塊中的函數(shù),把這個模塊的名稱空間當(dāng)做全局名稱空間,這樣在編寫自己的模塊時,就不用擔(dān)心定義在自己模塊中的全局變量會在被導(dǎo)入時,與使用者的全局變量沖突。
為模塊起別名:
import spam as sm
在一行中導(dǎo)入多個模塊
from spam import read1,read2
3、使用模塊之from ... import ...
4、模塊搜索路徑
#模塊的查找順序 1、在第一次導(dǎo)入某個模塊時(比如spam),會先檢查該模塊是否已經(jīng)被加載到內(nèi)存中(當(dāng)前執(zhí)行文件的名稱空間對應(yīng)的內(nèi)存),如果有則直接引用ps:python解釋器在啟動時會自動加載一些模塊到內(nèi)存中,可以使用sys.modules查看 2、如果沒有,解釋器則會查找同名的內(nèi)建模塊 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.#需要特別注意的是:我們自定義的模塊名不應(yīng)該與系統(tǒng)內(nèi)置模塊重名。雖然每次都說,但是仍然會有人不停的犯錯。 #在初始化后,python程序可以修改sys.path,路徑放到前面的優(yōu)先于標(biāo)準(zhǔn)庫被加載。 >>> import sys >>> sys.path.append('/a/b/c/d') >>> sys.path.insert(0,'/x/y/z') #排在前的目錄,優(yōu)先被搜索 注意:搜索時按照sys.path中從左到右的順序查找,位于前的優(yōu)先被查找,sys.path中還可能包含.zip歸檔文件和.egg文件,python會把.zip歸檔文件當(dāng)成一個目錄去處理,#首先制作歸檔文件:zip module.zip foo.py bar.py import sys sys.path.append('module.zip') import foo,bar#也可以使用zip中目錄結(jié)構(gòu)的具體位置 sys.path.append('module.zip/lib/python')#windows下的路徑不加r開頭,會語法錯誤 sys.path.insert(0,r'C:\Users\Administrator\PycharmProjects\a')#至于.egg文件是由setuptools創(chuàng)建的包,這是按照第三方python庫和擴(kuò)展時使用的一種常見格式,.egg文件實際上只是添加了額外元數(shù)據(jù)(如版本號,依賴項等)的.zip文件。#需要強(qiáng)調(diào)的一點(diǎn)是:只能從.zip文件中導(dǎo)入.py,.pyc等文件。使用C編寫的共享庫和擴(kuò)展塊無法直接從.zip文件中加載(此時setuptools等打包系統(tǒng)有時能提供一種規(guī)避方法),且從.zip中加載文件不會創(chuàng)建.pyc或者.pyo文件,因此一定要事先創(chuàng)建他們,來避免加載模塊是性能下降。
?
? 5、包介紹
什么是包?
1. 在python3中,即使包下沒有__init__.py文件,import 包仍然不會報錯,而在python2中,包下一定要有該文件,否則import 包報錯2. 創(chuàng)建包的目的不是為了運(yùn)行,而是被導(dǎo)入使用,記住,包只是模塊的一種形式而已,包的本質(zhì)就是一種模塊
為什么要使用包?
包的本質(zhì)就是一個文件夾,那么文件夾唯一的功能就是將文件組織起來
隨著功能越寫越多,我們無法將所以功能都放到一個文件中,于是我們使用模塊去組織功能,而隨著模塊越來越多,我們就需要用文件夾將模塊文件組織起來,以此來提高程序的結(jié)構(gòu)性和可維護(hù)性 ?
?
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
?
#文件內(nèi)容#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)
?
執(zhí)行文件與示范文件在同級目錄下
2、包的使用之import
1 import glance.db.models 2 glance.db.models.register_models('mysql') 單獨(dú)導(dǎo)入包名稱時不會導(dǎo)入包中所有包含的所有子模塊,如#在與glance同級的test.py中 import glance glance.cmd.manage.main()''' 執(zhí)行結(jié)果: 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 執(zhí)行:1 #在于glance同級的test.py中 2 import glance 3 glance.cmd.manage.main() 3、包的使用之from ... import ..
?
需要注意的是from后import導(dǎo)入的模塊,必須是明確的一個不能帶點(diǎn),否則會有語法錯誤,如: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 *
?
在講模塊時,我們已經(jīng)討論過了從一個模塊內(nèi)導(dǎo)入所有*,此處我們研究從一個包導(dǎo)入所有*。
此處是想從包api中導(dǎo)入所有,實際上該語句只會導(dǎo)入包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同級的文件中執(zhí)行from glance.api import *就導(dǎo)入__all__中的內(nèi)容(versions仍然不能導(dǎo)入)。
#執(zhí)行文件中的使用效果如下,請?zhí)幚砗冒膶?dǎo)入 from glance import *get() create_resource('a.conf') main() register_models('mysql')
?
5、絕對導(dǎo)入和相對導(dǎo)入
我們的最頂級包glance是寫給別人用的,然后在glance包內(nèi)部也會有彼此之間互相導(dǎo)入的需求,這時候就有絕對導(dǎo)入和相對導(dǎo)入兩種方式:
絕對導(dǎo)入:以glance作為起始
相對導(dǎo)入:用.或者..的方式最為起始(只能在一個包中使用,不能用于不同目錄內(nèi))
例如:我們在glance/api/version.py中想要導(dǎo)入glance/cmd/manage.py
?
1 在glance/api/version.py 2 3 #絕對導(dǎo)入 4 from glance.cmd import manage 5 manage.main() 6 7 #相對導(dǎo)入 8 from ..cmd import manage 9 manage.main()
?
測試結(jié)果:注意一定要在于glance同級的文件中測試
1 from glance.api import versions
6、包以及包所包含的模塊都是用來被導(dǎo)入的,而不是被直接執(zhí)行的。而環(huán)境變量都是以執(zhí)行文件為準(zhǔn)的
比如我們想在glance/api/versions.py中導(dǎo)入glance/api/policy.py,有的同學(xué)一抽這倆模塊是在同一個目錄下,十分開心的就去做了,它直接這么做
1 #在version.py中 2 3 import policy 4 policy.get()
沒錯,我們單獨(dú)運(yùn)行version.py是一點(diǎn)問題沒有的,運(yùn)行version.py的路徑搜索就是從當(dāng)前路徑開始的,于是在導(dǎo)入policy時能在當(dāng)前目錄下找到
但是你想啊,你子包中的模塊version.py極有可能是被一個glance包同一級別的其他文件導(dǎo)入,比如我們在于glance同級下的一個test.py文件中導(dǎo)入version.py,如下
?
1 from glance.api import versions 2 3 ''' 4 執(zhí)行結(jié)果: 5 ImportError: No module named 'policy' 6 ''' 7 8 ''' 9 分析: 10 此時我們導(dǎo)入versions在versions.py中執(zhí)行 11 import policy需要找從sys.path也就是從當(dāng)前目錄找policy.py, 12 這必然是找不到的 13 '''
?
二、常用模塊
logging模塊
日志級別
CRITICAL = 50 #FATAL = CRITICAL ERROR = 40 WARNING = 30 #WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0 #不設(shè)置
默認(rèn)級別為warning,默認(rèn)打印到終端
import logginglogging.debug('調(diào)試debug') logging.info('消息info') logging.warning('警告warn') logging.error('錯誤error') logging.critical('嚴(yán)重critical')''' WARNING:root:警告warn ERROR:root:錯誤error CRITICAL:root:嚴(yán)重critical '''
為logging模塊指定全局配置,針對所有l(wèi)ogger有效,控制打印到文件中
復(fù)制代碼 可在logging.basicConfig()函數(shù)中通過具體參數(shù)來更改logging模塊默認(rèn)行為,可用參數(shù)有 filename:用指定的文件名創(chuàng)建FiledHandler(后邊會具體講解handler的概念),這樣日志會被存儲在指定的文件中。 filemode:文件打開方式,在指定了filename時使用這個參數(shù),默認(rèn)值為“a”還可指定為“w”。 format:指定handler使用的日志顯示格式。 datefmt:指定日期時間格式。 level:設(shè)置rootlogger(后邊會講解具體概念)的日志級別 stream:用指定的stream創(chuàng)建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件,默認(rèn)為sys.stderr。若同時列出了filename和stream兩個參數(shù),則stream參數(shù)會被忽略。#格式 %(name)s:Logger的名字,并非用戶名,詳細(xì)查看%(levelno)s:數(shù)字形式的日志級別%(levelname)s:文本形式的日志級別%(pathname)s:調(diào)用日志輸出函數(shù)的模塊的完整路徑名,可能沒有%(filename)s:調(diào)用日志輸出函數(shù)的模塊的文件名%(module)s:調(diào)用日志輸出函數(shù)的模塊名%(funcName)s:調(diào)用日志輸出函數(shù)的函數(shù)名%(lineno)d:調(diào)用日志輸出函數(shù)的語句所在的代碼行%(created)f:當(dāng)前時間,用UNIX標(biāo)準(zhǔn)的表示時間的浮 點(diǎn)數(shù)表示%(relativeCreated)d:輸出日志信息時的,自Logger創(chuàng)建以 來的毫秒數(shù)%(asctime)s:字符串形式的當(dāng)前時間。默認(rèn)格式是 “2003-07-08 16:49:45,896”。逗號后面的是毫秒%(thread)d:線程ID。可能沒有%(threadName)s:線程名。可能沒有%(process)d:進(jìn)程ID。可能沒有%(message)s:用戶輸出的消息
?
#======介紹 可在logging.basicConfig()函數(shù)中可通過具體參數(shù)來更改logging模塊默認(rèn)行為,可用參數(shù)有 filename:用指定的文件名創(chuàng)建FiledHandler(后邊會具體講解handler的概念),這樣日志會被存儲在指定的文件中。 filemode:文件打開方式,在指定了filename時使用這個參數(shù),默認(rèn)值為“a”還可指定為“w”。 format:指定handler使用的日志顯示格式。 datefmt:指定日期時間格式。 level:設(shè)置rootlogger(后邊會講解具體概念)的日志級別 stream:用指定的stream創(chuàng)建StreamHandler。可以指定輸出到sys.stderr,sys.stdout或者文件,默認(rèn)為sys.stderr。若同時列出了filename和stream兩個參數(shù),則stream參數(shù)會被忽略。format參數(shù)中可能用到的格式化串: %(name)s Logger的名字 %(levelno)s 數(shù)字形式的日志級別 %(levelname)s 文本形式的日志級別 %(pathname)s 調(diào)用日志輸出函數(shù)的模塊的完整路徑名,可能沒有 %(filename)s 調(diào)用日志輸出函數(shù)的模塊的文件名 %(module)s 調(diào)用日志輸出函數(shù)的模塊名 %(funcName)s 調(diào)用日志輸出函數(shù)的函數(shù)名 %(lineno)d 調(diào)用日志輸出函數(shù)的語句所在的代碼行 %(created)f 當(dāng)前時間,用UNIX標(biāo)準(zhǔn)的表示時間的浮 點(diǎn)數(shù)表示 %(relativeCreated)d 輸出日志信息時的,自Logger創(chuàng)建以 來的毫秒數(shù) %(asctime)s 字符串形式的當(dāng)前時間。默認(rèn)格式是 “2003-07-08 16:49:45,896”。逗號后面的是毫秒 %(thread)d 線程ID。可能沒有 %(threadName)s 線程名。可能沒有 %(process)d 進(jìn)程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('調(diào)試debug') logging.info('消息info') logging.warning('警告warn') logging.error('錯誤error') logging.critical('嚴(yán)重critical')#========結(jié)果 access.log內(nèi)容: 2017-07-28 20:32:17 PM - root - DEBUG -test: 調(diào)試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: 嚴(yán)重criticalpart2: 可以為logging模塊指定模塊級的配置,即所有l(wèi)ogger的配置
?
4、logging模塊的Formatter,Handler,Logger,Filter對象
#logger:產(chǎn)生日志的對象#Filter:過濾日志的對象#Handler:接收日志然后控制打印到不同的地方,FileHandler用來打印到文件中,StreamHandler用來打印到終端#Formatter對象:可以定制不同的日志格式對象,然后綁定給不同的Handler對象使用,以此來控制不同的Handler的日志格式
?
''' critical=50 error =40 warning =30 info = 20 debug =10 '''import logging#1、logger對象:負(fù)責(zé)產(chǎn)生日志,然后交給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并設(shè)置日志級別 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,可以設(shè)置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 loggingform=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.應(yīng)用
""" 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'# 定義日志輸出格式 結(jié)束 logfile_dir = os.path.dirname(os.path.abspath(__file__)) # log文件的目錄 logfile_name = 'all2.log' # log文件名# 如果不存在定義的日志目錄就創(chuàng)建一個 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', # 日志文件的編碼,再也不用擔(dān)心中文log亂碼了 },},'loggers': {#logging.getLogger(__name__)拿到的logger配置'': {'handlers': ['default', 'console'], # 這里把上面定義的兩個handler都加上,即log數(shù)據(jù)既寫入文件又打印到屏幕'level': 'DEBUG','propagate': True, # 向上(更高level的logger)傳遞 },}, }def load_my_logging_cfg():logging.config.dictConfig(LOGGING_DIC) # 導(dǎo)入上面定義的logging配置logger = logging.getLogger(__name__) # 生成一個log實例logger.info('It works!') # 記錄該文件的運(yùn)行狀態(tài)if __name__ == '__main__':load_my_logging_cfg()
""" MyLogging Test """import time import logging import my_logging # 導(dǎo)入自定義的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("中文測試結(jié)束。。。")if __name__ == "__main__":my_logging.load_my_logging_cfg() # 在你程序文件的入口加載自定義logging配置demo()
?
#1、有了上述方式我們的好處是:所有與logging模塊有關(guān)的配置都寫到字典中就可以了,更加清晰,方便管理#2、我們需要解決的問題是:1、從字典加載配置:logging.config.dictConfig(settings.LOGGING_DIC)2、拿到logger對象來產(chǎn)生日志logger對象都是配置到字典的loggers 鍵對應(yīng)的子字典中的按照我們對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__不同,這保證了打印日志時標(biāo)識信息不同,但是拿著該名字去loggers里找key名時卻發(fā)現(xiàn)找不到,于是默認(rèn)使用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']# 重復(fù)匹配:| . | * | ? | .* | .*? | + | {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'] #匹配所有包含小數(shù)在內(nèi)的數(shù)字 print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3']#.*默認(rèn)為貪婪匹配 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')) #[]內(nèi)的都為普通字符了,且如果-沒有被轉(zhuǎn)意的話,應(yīng)該放到[]的開頭或結(jié)尾 print(re.findall('a[^1*-]b','a1b a*b a-b a=b')) #[]內(nèi)的^代表的意思是取反,所以結(jié)果為['a=b'] print(re.findall('a[0-9]b','a1b a*b a-b a=b')) #[]內(nèi)的^代表的意思是取反,所以結(jié)果為['a=b'] print(re.findall('a[a-z]b','a1b a*b a-b a=b aeb')) #[]內(nèi)的^代表的意思是取反,所以結(jié)果為['a=b'] print(re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb')) #[]內(nèi)的^代表的意思是取反,所以結(jié)果為['a=b']#\# print(re.findall('a\\c','a\c')) #對于正則來說a\\c確實可以匹配到a\c,但是在python解釋器讀取a\\c時,會發(fā)生轉(zhuǎn)義,然后交給re去執(zhí)行,所以拋出異常 print(re.findall(r'a\\c','a\c')) #r代表告訴解釋器使用rawstring,即原生字符串,把我們正則內(nèi)的所有符號都當(dāng)普通字符處理,不要轉(zhuǎn)義 print(re.findall('a\\\\c','a\c')) #同上面的意思一樣,和上面的結(jié)果一樣都是['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的結(jié)果不是匹配的全部內(nèi)容,而是組內(nèi)的內(nèi)容,?:可以讓結(jié)果為匹配的全部內(nèi)容 print(re.findall('href="(.*?)"','<a href="http://www.baidu.com">點(diǎn)擊</a>'))#['http://www.baidu.com'] print(re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">點(diǎn)擊</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 #1 print(re.findall('e','alex make love') ) #['e', 'e', 'e'],返回所有滿足匹配條件的結(jié)果,放在列表里 #2 print(re.search('e','alex make love').group()) #e,只到找到第一個匹配然后返回一個包含匹配信息的對象,該對象可以通過調(diào)用group()方法得到匹配的字符串,如果字符串沒有匹配,則返回None。#3 print(re.match('e','alex make love')) #None,同search,不過在字符串開始處進(jìn)行匹配,完全可以用search+^代替match#4 print(re.split('[ab]','abcd')) #['', '', 'cd'],先按'a'分割得到''和'bcd',再對''和'bcd'分別按'b'分割#5 print('===>',re.sub('a','A','alex make love')) #===> Alex mAke love,不指定n,默認(rè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 alexprint('===>',re.subn('a','A','alex make love')) #===> ('Alex mAke love', 2),結(jié)果帶有總共替換的個數(shù)#6 obj=re.compile('\d{2}')print(obj.search('abc123eeee').group()) #12 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 reprint(re.findall(r'-?\d+\.?\d*',"1-12*(60+(-40.35/5)-(-4*3))")) #找出所有數(shù)字['1', '-12', '60', '-40.35', '5', '-4', '3']#使用|,先匹配的先生效,|左邊是匹配小數(shù),而findall最終結(jié)果是查看分組,所有即使匹配成功小數(shù)也不會存入結(jié)果 #而不是小數(shù)時,就去匹配(-?\d+),匹配到的自然就是,非小數(shù)的數(shù),在此處即整數(shù) print(re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")) #找出所有整數(shù)['1', '-2', '60', '', '5', '-4', '3']
?
轉(zhuǎn)載于:https://www.cnblogs.com/mrwang1101/p/8232709.html
總結(jié)
以上是生活随笔為你收集整理的Python20-Day05的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 查唐筛多少钱啊?
- 下一篇: 管理员技术(六): 硬盘分区及格式化、