一.反射(自省)
首先通過一個例子來看一下本文中可能用到的物件和相關概念。
import sys # 模組,sys指向這個模組物件
import inspect
def foo(): pass # 函式,foo指向這個函式物件
class Cat(object): # 類,Cat指向這個類物件
def __init__(self, name='kitty'):
self.name = name
def sayHi(self): # 例項方法,sayHi指向這個方法物件,使用類或例項.sayHi訪問
print(self.name), 'says Hi!' # 訪問名為name的欄位,使用例項.name訪問
cat = Cat()#cat 是Cat類的例項物件
print(Cat.sayHi) # 使用類名訪問例項方法時,方法是未繫結的(unbound)
>>> <function Cat.sayHi at 0x101478378>
print(cat.sayHi) # 使用例項訪問例項方法時,方法是繫結的(bound)
>>> <bound method Cat.sayHi of <__main__.Cat object at 0x101178e48>>
有時候我們會碰到這樣的需求,需要執行物件的某個方法,或是需要對物件的某個欄位賦值,而方法名或是欄位名在編碼程式碼時並不能確定,需要通過引數傳遞字串的形式輸入。舉個具體的例子:當我們需要實現一個通用的DBM框架時,可能需要對資料物件的欄位賦值,但我們無法預知用到這個框架的資料物件都有些什麼欄位,換言之,我們在寫框架的時候需要通過某種機制訪問未知的屬性。
這個機制被稱為反射(反過來讓物件告訴我們他是什麼),或是自省(讓物件自己告訴我們他是什麼,好吧我承認括號裡是我瞎掰的- -#),用於實現在執行時獲取未知物件的資訊。反射是個很嚇唬人的名詞,聽起來高深莫測,在一般的程式語言裡反射相對其他概念來說稍顯複雜,一般來說都是作為高階主題來講;但在Python中反射非常簡單,用起來幾乎感覺不到與其他的程式碼有區別,使用反射獲取到的函式和方法可以像平常一樣加上括號直接呼叫,獲取到類後可以直接構造例項;不過獲取到的欄位不能直接賦值,因為拿到的其實是另一個指向同一個地方的引用,賦值只能改變當前的這個引用而已。
1. 訪問物件的屬性
以下列出了幾個內建方法,可以用來檢查或是訪問物件的屬性。這些方法可以用於任意物件而不僅僅是例子中的Cat例項物件;Python中一切都是物件。
def foo(): pass # 函式,foo指向這個函式物件
class Cat(object): # 類,Cat指向這個類物件
def __init__(self, name='kitty'):
self.name = name
def sayHi(self): # 例項方法,sayHi指向這個方法物件,使用類或例項.sayHi訪問
print(self.name), 'says Hi!' # 訪問名為name的欄位,使用例項.name訪問
cat = Cat('kitty')
print(cat.name) # 訪問例項屬性
>>>kitty
cat.sayHi() # 呼叫例項方法
>>>kitty
print(dir(cat)) # 獲取例項的屬性名,以列表形式返回
>>>['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'sayHi']
if hasattr(cat, 'name'): # 檢查例項是否有這個屬性
setattr(cat, 'name', 'tiger') # same as: a.name = 'tiger'
print(getattr(cat, 'name')) # same as: print a.name
>>>tiger
getattr(cat, 'sayHi')() # same as: cat.sayHi()
>>>tiger
- dir([obj]):
呼叫這個方法將返回包含obj大多數屬性名的列表(會有一些特殊的屬性不包含在內)。obj的預設值是當前的模組物件。
- hasattr(obj, attr):
這個方法用於檢查obj是否有一個名為attr的值的屬性,返回一個布林值。
- getattr(obj, attr):
呼叫這個方法將返回obj中名為attr值的屬性的值,例如如果attr為'bar',則返回obj.bar。
- setattr(obj, attr, val):
呼叫這個方法將給obj的名為attr的值的屬性賦值為val。例如如果attr為'bar',則相當於obj.bar = val。
例子:
自定義模組commons.py如下
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
def login():
print('登入介面')
def logout():
print('登出介面')
def home():
print('home介面')
在另外一個index指令碼中匯入commons模組,具體如下所示
import commons
def run():
inp = input('輸入你要執行的函式名')
#inp 字串型別 eg. inp = 'login'
# delattr()
# setattr()
#利用字串對模組進行操作(增加,刪除,修改,查詢)
if hasattr(commons,inp):#判斷commons是否存在inp函式,如果存在獲取此函式,否則404
func = getattr(commons,inp)#獲取commons下的inp對應的函式
func()#執行對應的函式
else:
print('404')
通過__import__字串方式匯入函式,需要輸入模組名和此模組下的函式名
def run():
inp = input('account/function')
m,f = inp.split('/')
obj = __import__(m)#匯入包及
if hasattr(obj,f):
func = getattr(obj,f)
func()
else:
print('404')
if __name__ == '__main__':
run()
*模組內建引數補充說明*
- __doc__: 文件字串。如果模組沒有文件,這個值是None。
- *__name__: 始終是定義時的模組名;即使你使用import .. as 為它取了別名,或是賦值給了另一個變數名。
- *__dict__: 包含了模組裡可用的屬性名-屬性的字典;也就是可以使用模組名.屬性名訪問的物件
- __file__: 包含了該模組的檔案路徑。需要注意的是內建的模組沒有這個屬性,訪問它會丟擲異常!
commons.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: Jason Wang
# commons.py
"""
document for fanshe
"""
def login():
print('登入介面')
def logout():
print('登出介面')
def home():
print('home介面')
##執行結果
print(__name__)
>>>__main__
index指令碼匯入commons
>>>document for fanshe
print(com.__name__)# commons指令碼名
>>>commons
print(com.__file__)
二.hashlib模組
用於加密相關的操作,3.x裡代替了md5模組和sha模組,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 演算法
import hashlib
m = hashlib.md5()
m.update(b"Hello")
m.update(b"It's me")
print(m.digest())
m.update(b"It's been a long time since last time we ...")
print(m.digest()) #2進位制格式hash
print(len(m.hexdigest())) #16進位制格式hash
'''
def digest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of binary data. """
pass
def hexdigest(self, *args, **kwargs): # real signature unknown
""" Return the digest value as a string of hexadecimal digits. """
pass
'''
import hashlib
# ######## md5 ########
hash = hashlib.md5()
hash.update('admin')
print(hash.hexdigest())
# ######## sha1 ########
hash = hashlib.sha1()
hash.update('admin')
print(hash.hexdigest())
# ######## sha256 ########
hash = hashlib.sha256()
hash.update('admin')
print(hash.hexdigest())
# ######## sha384 ########
hash = hashlib.sha384()
hash.update('admin')
print(hash.hexdigest())
# ######## sha512 ########
hash = hashlib.sha512()
hash.update('admin')
print(hash.hexdigest())
還不夠吊?python 還有一個 hmac 模組,它內部對我們建立 key 和 內容 再進行處理然後再加密
import hmac
h = hmac.new('Jason')
h.update('hellowo')
print h.hexdigest()
更多關於md5,sha1,sha256等介紹的文章看這裡https://www.tbs-certificates.co.uk/FAQ/en/sha256.html
三.正規表示式
1、Python支援的正規表示式元字元和語法
語法 | 說明 | 表示式例項 | 完整匹配的字串 |
字元 | |||
一般字元 | 匹配自己 | abc | abc |
. | 匹配任意字元“\n”除外 DOTALL模式中(re.DOTALL)也能匹配換行符 |
a.b | abc或abc或a1c等 |
[...] | 字符集[abc]表示a或b或c,也可以-表示一個範圍如[a-d]表示a或b或c或d | a[bc]c | abc或adc |
[^...] | 非字符集,也就是非[]裡的之外的字元 | a[^bc]c | adc或aec等 |
預定義字符集(也可以系在字符集[...]中) | |||
\d | 數字:[0-9] | a\dc | a1c等 |
\D | 非數字:[^0-9]或[^\d] | a\Dc | abc等 |
\s | 空白字元:[<空格>\t\n\f\v] | a\sc | a b等 |
\S | 非空白字元:[^s] | a\Sc | abc等 |
\w | 字母數字(單詞字元)[a-zA-Z0-9] | a\wc | abc或a1c等 |
\W | 非字母數字(非單詞字元)[^\w] | a\Wc | a.c或a_c等 |
數量詞(用在字元或(...)分組之後) | |||
* | 匹配0個或多個前面的表示式。(注意包括0次) | abc* | ab或abcc等 |
+ | 匹配1個或多個前面的表示式。 | abc+ | abc或abcc等 |
? | 匹配0個或1個前面的表示式。(注意包括0次) | abc? | ab或abc |
{m} | 匹配m個前面表示式(非貪婪) | abc{2} | abcc |
{m,} | 匹配至少m個前面表示式(m至無限次) | abc{2,} | abcc或abccc等 |
{m,n} | 匹配m至n個前面的表示式 | abc{1,2} | abc或abcc |
邊界匹配(不消耗待匹配字元中的字元) | |||
^ | 匹配字串開頭,在多行模式中匹配每一行的開頭 | ^abc | abc或abcd等 |
$ | 匹配字串結尾,在多行模式中匹配每一行的結尾 | abc$ | abc或123abc等 |
\A | 僅匹配字串開頭 | \Aabc | abc或abcd等 |
\Z | 僅匹配字串結尾 | abc\Z | abc或123abc等 |
\b | 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 | ||
\B | 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 | ||
邏輯、分組 | |||
| | 或左右表示式任意一個(短路)如果|沒有在()中表示整個正規表示式(注意有括號和沒括號的區別) | abc|def ab(c|d)ef |
abc或def abcef或abdef |
(...) | 分組,可以用來引用,也可以括號內的被當做一組進行數量匹配後接數量詞 | (abc){2}a | abcabca |
(?P<name>...) | 分組別名,給分組起個名字,方便後面呼叫 | ||
\<number> | 引用編號為<number>的分組匹配到的字串(注意是配到的字串不是分組表示式本身) | (\d)abc\1 | 1ab1或5ab5等 |
(?=name) | 引用別名為name的分組匹配到的字串(注意是配到的字串不是分組表示式本身) | (?P<id>\d)abc(?P=id) | 1ab1或5ab5等 |
一簡介:
就其本質而言,正規表示式(或 RE)是一種小型的、高度專業化的程式語言,
(在Python中)它內嵌在Python中,並通過 re 模組實現。正規表示式模式被
編譯成一系列的位元組碼,然後由用 C 編寫的匹配引擎執行。
二
字元匹配(普通字元,元字元):
普通字元:大多數字符和字母都會和自身匹配
>>> re.findall('alex','yuanaleSxalexwupeiqi')
['alex']
2元字元:. ^ $ * + ? { } [ ] | ( ) \
我們首先考察的元字元是"[" 和 "]"。它們常用來指定一個字元類別,所謂字元類
別就是你想匹配的一個字符集。字元可以單個列出,也可以用“-”號分隔的兩個給定
字元來表示一個字元區間。例如,[abc] 將匹配"a", "b", 或 "c"中的任意一個字
符;也可以用區間[a-c]來表示同一字符集,和前者效果一致。如果你只想匹配小寫
字母,那麼 RE 應寫成 [a-z].
元字元在類別裡並不起作用。例如,[akm$]將匹配字元"a", "k", "m", 或 "$" 中
的任意一個;"$"通常用作元字元,但在字元類別裡,其特性被除去,恢復成普通字
符。
():
#!python
>>> p = re.compile('(a(b)c)d')
>>> m = p.match('abcd')
>>> m.group(0)
'abcd'
>>> m.group(1)
'abc'
>>> m.group(2)
'b'
[]:元字元[]表示字元類,在一個字元類中,只有字元^、-、]和\有特殊含義。
字元\仍然表示轉義,字元-可以定義字元範圍,字元^放在前面,表示非.
+ 匹配+號前內容1次至無限次
? 匹配?號前內容0次到1次
{m} 匹配前面的內容m次
{m,n} 匹配前面的內容m到n次
*?,+?,??,{m,n}? 前面的*,+,?等都是貪婪匹配,也就是儘可能匹配,後面加?號使其變成惰性匹配
從前面的描述可以看到'*','+'和'*'都是貪婪的,但這也許並不是我們說要的,
所以,可以在後面加個問號,將策略改為非貪婪,只匹配儘量少的RE。示例,
體會兩者的區別:
>>> re.findall(r"a(\d+?)","a23b") # 非貪婪模式
['2']
>>> re.findall(r"a(\d+)","a23b")
['23']
>>> re.search('<(.*)>', '<H1>title</H1>').group()
'<H1>title</H1>'
re.search('<(.*?)>', '<H1>title</H1>').group()
'<H1>'
注意比較這種情況:
>>> re.findall(r"a(\d+)b","a23b")
['23']
>>> re.findall(r"a(\d+?)b","a23b") #如果前後均有限定條件,則非匹配模式失效
['23']
\:
反斜槓後邊跟元字元去除特殊功能,
反斜槓後邊跟普通字元實現特殊功能。
引用序號對應的字組所匹配的字串
re.search(r"(alex)(eric)com\2","alexericcomeric")
\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: 匹配一個單詞邊界,也就是指單詞和空格間的位置。
匹配單詞邊界(包括開始和結束),這裡的“單詞”,是指連續的字母、數字和
下劃線組成的字串。注意,\b的定義是\w和\W的交界,
這是個零寬界定符(zero-width assertions)只用以匹配單詞的詞首和詞尾。
單詞被定義為一個字母數字序列,因此詞尾就是用空白符或非字母數字符來標
示的。
>>> re.findall(r"abc\b","dzx &abc sdsadasabcasdsadasdabcasdsa")
['abc']
>>> re.findall(r"\babc\b","dzx &abc sdsadasabcasdsadasdabcasdsa")
['abc']
>>> re.findall(r"\babc\b","dzx sabc sdsadasabcasdsadasdabcasdsa")
[]
例如, 'er/b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\b只是匹配字串開頭結尾及空格回車等的位置, 不會匹配空格符本身
例如"abc sdsadasabcasdsadasdabcasdsa",
\sabc\s不能匹配,\babc\b可以匹配到"abc"
>>> re.findall("\babc\b","abc sdsadasabcasdsadasdabcasdsa")
[]
>>> re.findall(r"\babc\b","abc sdsadasabcasdsadasdabcasdsa")
['abc']
\b 就是用在你匹配整個單詞的時候。 如果不是整個單詞就不匹配。 你想匹
配 I 的話,你知道,很多單詞裡都有I的,但我只想匹配I,就是“我”,這個時
候用 \bI\b
************************************************
函式:
1
match:re.match(pattern, string, flags=0)
flags 編譯標誌位,用於修改正規表示式的匹配方式,如:是否區分大小寫,
多行匹配等等。
re.match('com', 'comwww.runcomoob').group()
re.match('com', 'Comwww.runComoob',re.I).group()
2
search:re.search(pattern, string, flags=0)
re.search('\dcom', 'www.4comrunoob.5com').group()
注意:
re.match('com', 'comwww.runcomoob')
re.search('\dcom', 'www.4comrunoob.5com')
一旦匹配成功,就是一個match object 物件,而match object 物件擁有以下方法:
group() 返回被 RE 匹配的字串
start() 返回匹配開始的位置
end() 返回匹配結束的位置
span() 返回一個元組包含匹配 (開始,結束) 的位置
group() 返回re整體匹配的字串,可以一次輸入多個組號,對應組號匹配的字串。
1. group()返回re整體匹配的字串,
2. group (n,m) 返回組號為n,m所匹配的字串,如果組號不存在,則返回indexError異常
3.groups()groups() 方法返回一個包含正規表示式中所有小組字串的元組,從 1 到
所含的小組號,通常groups()不需要引數,返回一個元組,元組中的元就是正則
表示式中定義的組。
import re
a = "123abc456"
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) #123abc456,返回整體
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1) #123
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2) #abc
re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3) #456
group(1) 列出第一個括號匹配部分,group(2) 列出第二個括號匹配部分,group(3)
列出第三個括號匹配部分。
-----------------------------------------------
3
findall:
re.findall 以列表形式返回所有匹配的字串
re.findall可以獲取字串中所有匹配的字串。如:
p = re.compile(r'\d+')
print p.findall('one1two2three3four4')
re.findall(r'\w*oo\w*', text);獲取字串中,包含'oo'的所有單詞。
import re
text = "JGood is a handsome boy,he is handsome and cool,clever,and so on ...."
print re.findall(r'\w*oo\w*',text) #結果:['JGood', 'cool']
#print re.findall(r'(\w)*oo(\w)*',text) # ()表示子表示式 結果:[('G', 'd'), ('c', 'l')]
finditer():
>>> p = re.compile(r'\d+')
>>> iterator = p.finditer('12 drumm44ers drumming, 11 ... 10 ...')
>>> for match in iterator:
match.group() , match.span()
4
sub subn:
re.sub(pattern, repl, string, max=0)
re.sub("g.t","have",'I get A, I got B ,I gut C')
5
split:
p = re.compile(r'\d+')
p.split('one1two2three3four4')
re.split('\d+','one1two2three3four4')
6
re.compile(strPattern[, flag]):
這個方法是Pattern類的工廠方法,用於將字串形式的正規表示式編譯為
Pattern物件。 第二個引數flag是匹配模式,取值可以使用按位或運算子'|'
表示同時生效,比如re.I | re.M
可以把正規表示式編譯成一個正規表示式物件。可以把那些經常使用的正則
表示式編譯成正規表示式物件,這樣可以提高一定的效率。下面是一個正規表示式
物件的一個例子:
import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
regex = re.compile(r'\w*oo\w*')
print regex.findall(text) #查詢所有包含'oo'的單詞
question:
1 findall能不能返回全組匹配的列表,而不是優先捕獲組的列表:yes,
import re
a = 'abc123abv23456'
b = re.findall(r'23(a)?',a)
print b
b = re.findall(r'23(?:a)?',a)
print b
>>> re.findall("www.(baidu|xinlang)\.com","www.baidu.com")
['baidu']
>>> re.findall("www.(?:baidu|xinlang)\.com","www.baidu.com")
['www.baidu.com']
>>> re.findall("www.(?:baidu|xinlang)\.com","www.xinlang.com")
['www.xinlang.com']
findall如果使用了分組,則輸出的內容將是分組中的內容而非find到的結果,
為了得到find到的結果,要加上問號來啟用“不捕捉模式”,就可以了。
2 re.findall('\d*', 'www33333')
3 re.split("[bc]","abcde")
4 source = "1 - 2 * ( (60-30 +(-9-2-5-2*3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )"
re.search('\([^()]*\)', source).group()regular='\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*'
re.search('\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*', string).group()
add_regular='[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*'
sub_regular='[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*'
re.findall(sub_regular, "(3+4-5+7+9)")
4 檢測一個IP地址:
re.search(r"(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5]\.)","192.168.1.1")
-----------------------------------------------------------
re.I 使匹配對大小寫不敏感
re.L 做本地化識別(locale-aware)匹配
re.M 多行匹配,影響 ^ 和 $
re.S 使 . 匹配包括換行在內的所有字元
>>> re.findall(".","abc\nde")
>>> re.findall(".","abc\nde",re.S)
re.U 根據Unicode字符集解析字元。這個標誌影響 \w, \W, \b, \B.
re.X 該標誌通過給予你更靈活的格式以便你將正規表示式寫得更易於理解。
re.S:.將會匹配換行符,預設.逗號不會匹配換行符
>>> re.findall(r"a(\d+)b.+a(\d+)b","a23b\na34b")
[]
>>> re.findall(r"a(\d+)b.+a(\d+)b","a23b\na34b",re.S)
[('23','34')]
>>>
re.M:^$標誌將會匹配每一行,預設^只會匹配符合正則的第一行;預設$只會匹配符合正則的末行
>>> re.findall(r"^a(\d+)b","a23b\na34b")
['23']
>>> re.findall(r"^a(\d+)b","a23b\na34b",re.M)
['23','34']
但是,如果沒有^標誌,
>>> re.findall(r"a(\d+)b","a23b\na34b")
['23','43']
可見,是無需re.M
import re
n='''12 drummers drumming,
11 pipers piping, 10 lords a-leaping'''
p=re.compile('^\d+')
p_multi=re.compile('^\d+',re.MULTILINE) #設定 MULTILINE 標誌
print re.findall(p,n) #['12']
print re.findall(p_multi,n) # ['12', '11']
============================
import re
a = 'a23b'
print re.findall('a(\d+?)',a) #['2']
print re.findall('a(\d+)',a) #['23']
print re.findall(r'a(\d+)b',a) #['23']
print re.findall(r'a(\d+?)b',a) # ['23']
============================
b='a23b\na34b'
''' . 匹配非換行符的任意一個字元'''
re.findall(r'a(\d+)b.+a(\d+)b',b) #[]
re.findall(r'a(\d+)b',b,re.M) # ['23', '34']
re.findall(r'^a(\d+)b',b,re.M) # ['23', '34']
re.findall(r'a(\d+)b',b) #['23','34'] 可以匹配多行
re.findall(r'^a(\d+)b',b) # ['23'] 預設^只會匹配符合正則的第一行
re.findall(r'a(\d+)b$',b) # ['34'] 預設$只會匹配符合正則的末行
re.findall(r'a(\d+)b',b,re.M) #['23', '34']
re.findall(r'a(\d+)b.?',b,re.M) # ['23', '34']
re.findall(r"a(\d+)b", "a23b\na34b") # ['23', '34']
---------------------------------------------------------------
推薦:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
*****關於rawstring以及\:
\n是換行,ASCLL碼是10
\r是回車,ASCLL碼是13
re.findall("\","abc\de")
f=open("C:\abc.txt")
\a是 轉義字元 007,響鈴符 BEL。
f=open(r"D:\abc.txt")
>>>>>>python自己也需要轉義,也是通過\轉義
>>> re.findall(r"\d","ww2ee")
['2']
>>> re.findall("\d","ww2ee")
['2']
>>強烈建議用raw字串來表述正則
你可能已經看到前面關於原始字串用法的一些例子了。原始字串的產生正是由於有正則表
達式的存在。原因是ASCII 字元和正規表示式特殊字元間所產生的衝突。比如,特殊符號“\b”在
ASCII 字元中代表退格鍵,但同時“\b”也是一個正規表示式的特殊符號,代表“匹配一個單詞邊界”。
為了讓RE 編譯器把兩個字元“\b”當成你想要表達的字串,而不是一個退格鍵,你需要用另一個
反斜線對它進行轉義,即可以這樣寫:“\\b”。
但這樣做會把問題複雜化,特別是當你的正規表示式字串裡有很多特殊字元時,就更容
易令人困惑了。原始字串就是被用於簡化正規表示式的複雜程度。
事實上,很多Python 程式設計師在定義正規表示式時都只使用原始字串。
下面的例子用來說明退格鍵“\b” 和正規表示式“\b”(包含或不包含原始字串)之間的區別:
>>> m = re.search('\bblow', 'blow') # backspace, no match #退格鍵,沒有匹配
>>> re.search('\\bblow', 'I blow').group() # escaped \, now it works #用\轉義後,現在匹
配了
>>> re.search(r'\bblow', 'I blow').group() # use raw string instead #改用原始字串
你可能注意到我們在正規表示式裡使用“\d”,沒用原始字串,也沒出現什麼問題。那是因為
ASCII 裡沒有對應的特殊字元,所以正規表示式編譯器能夠知道你指的是一個十進位制數字
######################
re模組的常用方法
re.compile(strPattern[, flag])
match(string[, pos[, endpos]]) | re.match(pattern, string[, flags])
search(string[, pos[, endpos]]) | re.search(pattern, string[, flags])
>>> import re
>>> s = 'hello world'
>>> print(re.match('ello', s))
None
>>> print(re.search('ello',s ))
<_sre.SRE_Match object; span=(1, 5), match='ello'>
說明:可以看到macth只匹配開頭,開頭不匹配,就不算匹配到,search則可以從中間,只要能有匹配到就算匹配
findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags])
搜尋string,以列表形式返回全部能匹配的子串。有點像search的擴充套件,把所有匹配的子串放到一個列表
引數:同match
返回值:所有匹配的子串,沒有匹配則返回空列表
>>> import re
>>> s = 'one1two2three3four4'
>>> re.findall('\d+', s)
['1', '2', '3', '4']
split(string[, maxsplit]) | re.split(pattern, string[, maxsplit]):
>>> import re
>>> s = 'one1two2three3four4'
>>> re.split('\d+',s)
['one', 'two', 'three', 'four', '']
sub(repl, string[, count]) | re.sub(pattern, repl, string[, count])
if __name__ == '__main__':
import re
s = '--(1.1+1+1-(-1)-(1+1+(1+1+2.2)))+-----111+--++--3-+++++++---+---1+4+4/2+(1+3)*4.1+(2-1.1)*2/2*3'
def replace_sign(expression):
'''
替換多個連續+-符號的問題,例如+-----,遵循奇數個負號等於正否則為負的原則進行替換
:param expression: 表示式,包括有括號的情況
:return: 返回經過處理的表示式
'''
def re_sign(m):
if m:
if m.group().count('-')%2 == 1:
return '-'
else:
return '+'
else:
return ''
expression = re.sub('[\+\-]{2,}', re_sign, expression)
return expression
s = replace_sign(s)
print(s)
執行結果
24 +(1.1+1+1-(-1)-(1+1+(1+1+2.2)))-111+3-1+4+4/2+(1+3)*4.1+(2-1.1)*2/2*3
四.冒泡
它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。
li = [1,2,33,55,2,77,6,88,9,25]
l = len(li)
氣泡排序
print(l)
for i in range(len(li)):
# print(li[i])
for j in range(l):
if li[i] > li[j]:
tmp = li[i]
li[i] = li[j]
li[j] = tmp
print(li)
#[88, 77, 55, 33, 25, 9, 6, 2, 1]
#選擇排序
# #index
# max_index = 0
# for j in range(len(li)):
# for i in range(len(li)-j):
# # print(i,li[i])
# # for j in range(l):
# if li[i] > li[max_index]:
# max_index = i
# print(max_index)
# # print(l-i)
#
# tmp = li[len(li)-j-1]
# li[len(li)-j-1] = li[max_index]
# li[max_index] = tmp
# print(li[len(li)-1])
# print(max_index)
# print(li)