python 面試題(高階)
42.Python中類方法、類例項方法、靜態方法有何區別?
類方法: 是類物件的方法,在定義時需要在上方使用 @classmethod 進行裝飾,形參為cls,表示類物件,類物件和例項物件都可呼叫
類例項方法: 是類例項化物件的方法,只有例項物件可以呼叫,形參為self,指代物件本身;
靜態方法: 是一個任意函式,在其上方使用 @staticmethod 進行裝飾,可以用物件直接呼叫,靜態方法實際上跟該類沒有太大關係
43.遍歷一個object的所有屬性,並print每一個屬性名?
class Car:
def __init__(self,name,loss): # loss [價格,油耗,公里數]
self.name = name
self.loss = loss
def getName(self):
return self.name
def getPrice(self):
# 獲取汽車價格
return self.loss[0]
def getLoss(self):
# 獲取汽車損耗值
return self.loss[1] * self.loss[2]
Bmw = Car("寶馬",[60,9,500]) # 例項化一個寶馬車物件
print(getattr(Bmw,"name")) # 使用getattr()傳入物件名字,屬性值。
print(dir(Bmw)) # 獲Bmw所有的屬性和方法
44.寫一個類,並讓它儘可能多的支援操作符?
class Array:
__list = []
def __init__(self):
print "constructor"
def __del__(self):
print "destruct"
def __str__(self):
return "this self-defined array class"
def __getitem__(self,key):
return self.__list[key]
def __len__(self):
return len(self.__list)
def Add(self,value):
self.__list.append(value)
def Remove(self,index):
del self.__list[index]
def DisplayItems(self):
print "show all items---"
for item in self.__list:
print item
45.介紹Cython,Pypy Cpython Numba各有什麼缺點
Cython
46.請描述抽象類和介面類的區別和聯絡
1.抽象類: 規定了一系列的方法,並規定了必須由繼承類實現的方法。由於有抽象方法的存在,所以抽象類不能例項化。可以將抽象類理解為毛坯房,門窗,牆面的樣式由你自己來定,所以抽象類與作為基類的普通類的區別在於約束性更強
2.介面類:與抽象類很相似,表現在介面中定義的方法,必須由引用類實現,但他與抽象類的根本區別在於用途:與不同個體間溝通的規則,你要進宿舍需要有鑰匙,這個鑰匙就是你與宿舍的介面,你的舍友也有這個介面,所以他也能進入宿舍,你用手機通話,那麼手機就是你與他人交流的介面
3.區別和關聯:
1.介面是抽象類的變體,介面中所有的方法都是抽象的,而抽象類中可以有非抽象方法,抽象類是宣告方法的存在而不去實現它的類
2.介面可以繼承,抽象類不行
3.介面定義方法,沒有實現的程式碼,而抽象類可以實現部分方法
4.介面中基本資料型別為static而抽象類不是
47.Python中如何動態獲取和設定物件的屬性?
if hasattr(Parent, 'x'):
print(getattr(Parent, 'x'))
setattr(Parent, 'x',3)
print(getattr(Parent,'x'))
記憶體管理與垃圾回收機制
48.哪些操作會導致Python記憶體溢位,怎麼處理?
49.關於Python記憶體管理,下列說法錯誤的是 B
A,變數不必事先宣告 B,變數無須先建立和賦值而直接使用
C,變數無須指定型別 D,可以使用del釋放資源
50.Python的記憶體管理機制及調優手段?
記憶體管理機制: 引用計數、垃圾回收、記憶體池
引用計數:引用計數是一種非常高效的記憶體管理手段,當一個Python物件被引用時其引用計數增加1,
當其不再被一個變數引用時則計數減1,當引用計數等於0時物件被刪除。弱引用不會增加引用計數
垃圾回收:
1.引用計數
引用計數也是一種垃圾收集機制,而且也是一種最直觀、最簡單的垃圾收集技術。當Python的某個物件的引用計數降為0時,說明沒有任何引用指向該物件,該物件就成為要被回收的垃圾了。比如某個新建物件,它被分配給某個引用,物件的引用計數變為1,如果引用被刪除,物件的引用計數為0,那麼該物件就可以被垃圾回收。不過如果出現迴圈引用的話,引用計數機制就不再起有效的作用了。
2.標記清除
https://foofish.net/python-gc.html
調優手段
1.手動垃圾回收
2.調高垃圾回收閾值
3.避免迴圈引用
51.記憶體洩露是什麼?如何避免?
記憶體洩漏指由於疏忽或錯誤造成程式未能釋放已經不再使用的記憶體。記憶體洩漏並非指記憶體在物理上的消失,而是應用程式分配某段記憶體後,由於設計錯誤,導致在釋放該段記憶體之前就失去了對該段記憶體的控制,從而造成了記憶體的浪費。
有__del__()
函式的物件間的迴圈引用是導致記憶體洩露的主凶。不使用一個物件時使用: del object 來刪除一個物件的引用計數就可以有效防止記憶體洩露問題。
通過Python擴充套件模組gc 來檢視不能回收的物件的詳細資訊。
可以通過 sys.getrefcount(obj) 來獲取物件的引用計數,並根據返回值是否為0來判斷是否記憶體洩露
函式
52.python常見的列表推導式?
[表示式 for 變數 in 列表] 或者 [表示式 for 變數 in 列表 if 條件]
53.簡述read、readline、readlines的區別?
read 讀取整個檔案
readline 讀取下一行
readlines 讀取整個檔案到一個迭代器以供我們遍歷
54.什麼是Hash(雜湊函式)?
雜湊函式(英語:Hash function)又稱雜湊演算法、雜湊函式,是一種從任何一種資料中建立小的數字“指紋”的方法。雜湊函式把訊息或資料壓縮成摘要,使得資料量變小,將資料的格式固定下來。該函式將資料打亂混合,重新建立一個叫做雜湊值(hash values,hash codes,hash sums,或hashes)的指紋。雜湊值通常用一個短的隨機字母和數字組成的字串來代表
55.python函式過載機制?
函式過載主要是為了解決兩個問題。 1。可變引數型別。 2。可變引數個數。
另外,一個基本的設計原則是,僅僅當兩個函式除了引數型別和引數個數不同以外,其功能是完全相同的,此時才使用函式過載,如果兩個函式的功能其實不同,那麼不應當使用過載,而應當使用一個名字不同的函式。
好吧,那麼對於情況 1 ,函式功能相同,但是引數型別不同,python 如何處理?答案是根本不需要處理,因為 python 可以接受任何型別的引數,如果函式的功能相同,那麼不同的引數型別在 python 中很可能是相同的程式碼,沒有必要做成兩個不同函式。
那麼對於情況 2 ,函式功能相同,但引數個數不同,python 如何處理?大家知道,答案就是預設引數。對那些缺少的引數設定為預設引數即可解決問題。因為你假設函式功能相同,那麼那些缺少的引數終歸是需要用的。
好了,鑑於情況 1 跟 情況 2 都有了解決方案,python 自然就不需要函式過載了。
56.寫一個函式找出一個整數陣列中,第二大的數
57.手寫一個判斷時間的裝飾器
import datetime
class TimeException(Exception):
def __init__(self, exception_info):
super().__init__()
self.info = exception_info
def __str__(self):
return self.info
def timecheck(func):
def wrapper(*args, **kwargs):
if datetime.datetime.now().year == 2019:
func(*args, **kwargs)
else:
raise TimeException("函式已過時")
return wrapper
@timecheck
def test(name):
print("Hello {}, 2019 Happy".format(name))
if __name__ == "__main__":
test("backbp")
58.使用Python內建的filter()方法來過濾?
list(filter(lambda x: x % 2 == 0, range(10)))
59.編寫函式的4個原則
1.函式設計要儘量短小
2.函式宣告要做到合理、簡單、易於使用
3.函式引數設計應該考慮向下相容
4.一個函式只做一件事情,儘量保證函式語句粒度的一致性
60.函式呼叫引數的傳遞方式是值傳遞還是引用傳遞?
Python的引數傳遞有:位置引數、預設引數、可變引數、關鍵字引數。
函式的傳值到底是值傳遞還是引用傳遞、要分情況:
不可變引數用值傳遞:像整數和字串這樣的不可變物件,是通過拷貝進行傳遞的,因為你無論如何都不可能在原處改變不可變物件。
可變引數是引用傳遞:比如像列表,字典這樣的物件是通過引用傳遞、和C語言裡面的用指標傳遞陣列很相似,可變物件能在函式內部改變。
61.如何在function裡面設定一個全域性變數
globals() # 返回包含當前作用餘全域性變數的字典。
global 變數 設定使用全域性變數
62.對預設引數的理解 ?
預設引數指在呼叫函式的時候沒有傳入引數的情況下,呼叫預設的引數,在呼叫函式的同時賦值時,所傳入的引數會替代預設引數。
*args是不定長引數,它可以表示輸入引數是不確定的,可以是任意多個。
**kwargs是關鍵字引數,賦值的時候是以鍵值對的方式,引數可以是任意多對在定義函式的時候
不確定會有多少引數會傳入時,就可以使用兩個引數
63.Mysql怎麼限制IP訪問?
64.帶引數的裝飾器?
帶定長引數的裝飾器
def new_func(func):
def wrappedfun(username, passwd):
if username == 'root' and passwd == '123456789':
print('通過認證')
print('開始執行附加功能')
return func()
else:
print('使用者名稱或密碼錯誤')
return
return wrappedfun
@new_func
def origin():
print('開始執行函式')
origin('root','123456789')
帶不定長引數的裝飾器
def new_func(func):
def wrappedfun(*parts):
if parts:
counts = len(parts)
print('本系統包含 ', end='')
for part in parts:
print(part, ' ',end='')
print('等', counts, '部分')
return func()
else:
print('使用者名稱或密碼錯誤')
return func()
return wrappedfun
65.為什麼函式名字可以當做引數用?
Python中一切皆物件,函式名是函式在記憶體中的空間,也是一個物件
66.Python中pass語句的作用是什麼?
在編寫程式碼時只寫框架思路,具體實現還未編寫就可以用pass進行佔位,是程式不報錯,不會進行任何操作。
67.有這樣一段程式碼,print c會輸出什麼,為什麼?
a = 10
b = 20
c = [a]
a = 15
答:10對於字串,數字,傳遞是相應的值
68.交換兩個變數的值?
a, b = b, a
69.map函式和reduce函式?
map(lambda x: x * x, [1, 2, 3, 4]) # 使用 lambda
# [1, 4, 9, 16]
reduce(lambda x, y: x * y, [1, 2, 3, 4]) # 相當於 ((1 * 2) * 3) * 4
# 24
70.回撥函式,如何通訊的?
回撥函式是把函式的指標(地址)作為引數傳遞給另一個函式,將整個函式當作一個物件,賦值給呼叫的函式。
71.Python主要的內建資料型別都有哪些? print dir( ‘a ’) 的輸出?
內建型別:布林型別,數字,字串,列表,元組,字典,集合
輸出字串'a'的內建方法
72.map(lambda x:xx,[y for y in range(3)])的輸出?
[0, 1, 4]
73.hasattr() getattr() setattr() 函式使用詳解?
hasattr(object,name)函式:
判斷一個物件裡面是否有name屬性或者name方法,返回bool值,有name屬性(方法)返回True,否則返回False。
class function_demo(object):
name = 'demo'
def run(self):
return "hello function"
functiondemo = function_demo()
res = hasattr(functiondemo, "name") # 判斷物件是否有name屬性,True
res = hasattr(functiondemo, "run") # 判斷物件是否有run方法,True
res = hasattr(functiondemo, "age") # 判斷物件是否有age屬性,False
print(res)
getattr(object, name[,default])函式:
獲取物件object的屬性或者方法,如果存在則打印出來,如果不存在,列印預設值,預設值可選。注意:如果返回的是物件的方法,則列印結果是:方法的記憶體地址,如果需要執行這個方法,可以在後面新增括號().
functiondemo = function_demo()
getattr(functiondemo, "name")# 獲取name屬性,存在就打印出來 --- demo
getattr(functiondemo, "run") # 獲取run 方法,存在打印出方法的記憶體地址
getattr(functiondemo, "age") # 獲取不存在的屬性,報錯
getattr(functiondemo, "age", 18)# 獲取不存在的屬性,返回一個預設值
setattr(object, name, values)函式:
給物件的屬性賦值,若屬性不存在,先建立再賦值
class function_demo(object):
name = "demo"
def run(self):
return "hello function"
functiondemo = function_demo()
res = hasattr(functiondemo, "age") # 判斷age屬性是否存在,False
print(res)
setattr(functiondemo, "age", 18) # 對age屬性進行賦值,無返回值
res1 = hasattr(functiondemo, "age") # 再次判斷屬性是否存在,True
綜合使用
class function_demo(object):
name = "demo"
def run(self):
return "hello function"
functiondemo = function_demo()
res = hasattr(functiondemo, "addr") # 先判斷是否存在
if res:
addr = getattr(functiondemo, "addr")
print(addr)
else:
addr = getattr(functiondemo, "addr", setattr(functiondemo, "addr", "北京首都"))
print(addr)
74.一句話解決階乘函式?
reduce(lambda x,y : x*y,range(1,n+1))
75.什麼是lambda函式? 有什麼好處?
lambda 函式是一個可以接收任意多個引數(包括可選引數)並且返回單個表示式值的函式
1.lambda函式比較輕便,即用即仍,很適合需要完成一項功能,但是此功能只在此一處使用,連名字都很隨意的情況下
2.匿名函式,一般用來給filter,map這樣的函數語言程式設計服務
3.作為回撥函式,傳遞給某些應用,比如訊息處理
76.遞迴函式停止的條件?
遞迴的終止條件一般定義在遞迴函式內部,在遞迴呼叫前要做一個條件判斷,根據判斷的結果選擇是繼續呼叫自身,還是return,,返回終止遞迴。
終止的條件:判斷遞迴的次數是否達到某一限定值
2.判斷運算的結果是否達到某個範圍等,根據設計的目的來選擇
77.下面這段程式碼的輸出結果將是什麼?請解釋。
def multipliers():
return [lambda x: i *x for i in range(4)]
print([m(2) for m in multipliers()])
上面程式碼的輸出結果是[6,6,6,6],不是我們想的[0,2,4,6]
你如何修改上面的multipliers的定義產生想要的結果?
上述問題產生的原因是python閉包的延遲繫結。這意味著內部函式被呼叫時,引數的值在閉包內進行查詢。因此,當任何由multipliers()返回的函式被呼叫時,i的值將在附近的範圍進行查詢。那時,不管返回的函式是否被呼叫,for迴圈已經完成,i被賦予了最終的值3.
def multipliers():
for i in range(4):
yield lambda x: i *x
def multipliers():
return [lambda x,i = i: i*x for i in range(4)]
78.什麼是lambda函式?它有什麼好處?寫一個匿名函式求兩個數的和
lambda函式是匿名函式,使用lambda函式能建立小型匿名函式,這種函式得名於省略了用def宣告函式的標準步驟
設計模式
79.對設計模式的理解,簡述你瞭解的設計模式?
設計模式是經過總結,優化的,對我們經常會碰到的一些程式設計問題的可重用解決方案。一個設計模式並不像一個類或一個庫那樣能夠直接作用於我們的程式碼,反之,設計模式更為高階,它是一種必須在特定情形下實現的一種方法模板。 常見的是工廠模式和單例模式
80.請手寫一個單例
#python2
class A(object):
__instance = None
def __new__(cls,*args,**kwargs):
if cls.__instance is None:
cls.__instance = objecet.__new__(cls)
return cls.__instance
else:
return cls.__instance
81.單例模式的應用場景有那些?
單例模式應用的場景一般發現在以下條件下: 資源共享的情況下,避免由於資源操作時導致的效能或損耗等,如日誌檔案,應用配置。 控制資源的情況下,方便資源之間的互相通訊。如執行緒池等,1,網站的計數器 2,應用配置 3.多執行緒池 4資料庫配置 資料庫連線池 5.應用程式的日誌應用...
82.用一行程式碼生成[1,4,9,16,25,36,49,64,81,100]
print([x*x for x in range(1, 11)])
83.對裝飾器的理解,並寫出一個計時器記錄方法執行效能的裝飾器?
裝飾器本質上是一個callable object ,它可以讓其他函式在不需要做任何程式碼變動的前提下增加額外功能,裝飾器的返回值也是一個函式物件。
import time
from functools import wraps
def timeit(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.clock()
ret = func(*args, **kwargs)
end = time.clock()
print('used:',end-start)
return ret
return wrapper
@timeit
def foo():
print('in foo()'foo())
84.解釋以下什麼是閉包?
在函式內部再定義一個函式,並且這個函式用到了外邊函式的變數,那麼將這個函式以及用到的一些變數稱之為閉包。
85.函式裝飾器有什麼作用?
裝飾器本質上是一個callable object,它可以在讓其他函式在不需要做任何程式碼的變動的前提下增加額外的功能。裝飾器的返回值也是一個函式的物件,它經常用於有切面需求的場景。比如:插入日誌,效能測試,事務處理,快取。許可權的校驗等場景,有了裝飾器就可以抽離出大量的與函式功能本身無關的雷同程式碼併發並繼續使用。 詳細參考:https://manjusaka.itscoder.com/2018/02/23/something-about-decorator/
86.生成器,迭代器的區別?
迭代器是遵循迭代協議的物件。使用者可以使用 iter() 以從任何序列得到迭代器(如 list, tuple, dictionary, set 等)。另一個方法則是建立一個另一種形式的迭代器 —— generator 。要獲取下一個元素,則使用成員函式 next()(Python 2)或函式 next() function (Python 3) 。當沒有元素時,則引發 StopIteration 此例外。若要實現自己的迭代器,則只要實現 next()(Python 2)或__next__
()( Python 3)
生成器(Generator),只是在需要返回資料的時候使用yield語句。每次next()被呼叫時,生成器會返回它脫離的位置(它記憶語句最後一次執行的位置和所有的資料值)
區別: 生成器能做到迭代器能做的所有事,而且因為自動建立iter()和next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器表示式取代列表解析可以同時節省記憶體。除了建立和儲存程式狀態的自動方法,當發生器終結時,還會自動丟擲StopIteration異常。
官方介紹:https://docs.python.org/3/tutorial/classes.html#iterators
87.X是什麼型別?
X= (i for i in range(10))
X是 generator型別
88.請用一行程式碼 實現將1-N 的整數列表以3為單位分組
N =100
print ([[x for x in range(1,100)] [i:i+3] for i in range(0,100,3)])
89.Python中yield的用法?
yield就是儲存當前程式執行狀態。你用for迴圈的時候,每次取一個元素的時候就會計算一次。用yield的函式叫generator,和iterator一樣,它的好處是不用一次計算所有元素,而是用一次算一次,可以節省很多空間,generator每次計算需要上一次計算結果,所以用yield,否則一return,上次計算結果就沒了
面向物件
90.Python中的可變物件和不可變物件?
不可變物件,該物件所指向的記憶體中的值不能被改變。當改變某個變數時候,由於其所指的值不能被改變,相當於把原來的值複製一份後再改變,這會開闢一個新的地址,變數再指向這個新的地址。
可變物件,該物件所指向的記憶體中的值可以被改變。變數(準確的說是引用)改變後,實際上其所指的值直接發生改變,並沒有發生複製行為,也沒有開闢出新的地址,通俗點說就是原地改變。
Pyhton中,數值型別(int 和float),字串str、元祖tuple都是不可變型別。而列表list、字典dict、集合set是可變型別
91.Python的魔法方法
魔法方法就是可以給你的類增加魔力的特殊方法,如果你的物件實現(過載)了這些方法中的某一個,那麼這個方法就會在特殊的情況下被Python所呼叫,你可以定義自己想要的行為,而這一切都是自動發生的,它們經常是兩個下劃線包圍來命名的(比如__init___
,__len__
),Python的魔法方法是非常強大的所以瞭解其使用方法也變得尤為重要!
__init__
構造器,當一個例項被建立的時候初始化的方法,但是它並不是例項化呼叫的第一個方法。
__new__
才是例項化物件呼叫的第一個方法,它只取下cls引數,並把其他引數傳給__init___
.
___new__
很少使用,但是也有它適合的場景,尤其是當類繼承自一個像元祖或者字串這樣不經常改變的型別的時候。
__call__
讓一個類的例項像函式一樣被呼叫
__getitem__
定義獲取容器中指定元素的行為,相當於self[key]
__getattr__
定義當用戶試圖訪問一個不存在屬性的時候的行為。
__setattr__
定義當一個屬性被設定的時候的行為
__getattribute___
定義當一個屬性被訪問的時候的行為
92.面向物件中怎麼實現只讀屬性?
將物件私有化,通過共有方法提供一個讀取資料的介面
class person:
def __init__(self, x):
self.__age = 10
def age(self):
return self.__age
t = person(22)
# t.__age =100
print(t.age())
最好的方法
class MyCls(object):
__weight = 50
@property
def weight(self):
return self.__weight
93.談談你對面向物件的理解?
面向物件是相當於面向過程而言的,面向過程語言是一種基於功能分析的,以演算法為中心的程式設計方法,而面向物件是一種基於結構分析的,以資料為中心的程式設計思想。在面嚮物件語言中有一個很重要的東西,叫做類。面向物件有三大特性:封裝、繼承、多型。
正則表示式
94.請寫出一段程式碼用正則匹配出ip?
95.a = “abbbccc”,用正則匹配為abccc,不管有多少b,就出現一次?
思路:不管有多少個b替換成一個
re.sub(r'b+', 'b', a)
96.Python字串查詢和替換?
a、str.find():正序字串查詢函式
函式原型:
str.find(substr [,pos_start [,pos_end ] ] )
返回str中第一次出現的substr的第一個字母的標號,如果str中沒有substr則返回-1,也就是說從左邊算起的第一次出現的substr的首字母標號。
引數說明:
str:代表原字串
substr:代表要查詢的字串
pos_start:代表查詢的開始位置,預設是從下標0開始查詢
pos_end:代表查詢的結束位置
例子:
'aabbcc.find('bb')' # 2
b、str.index():正序字串查詢函式
index()函式類似於find()函式,在Python中也是在字串中查詢子串第一次出現的位置,跟find()不同的是,未找到則丟擲異常。
函式原型:
str.index(substr [, pos_start, [ pos_end ] ] )
引數說明:
str:代表原字串
substr:代表要查詢的字串
pos_start:代表查詢的開始位置,預設是從下標0開始查詢
pos_end:代表查詢的結束位置
例子:
'acdd l1 23'.index(' ') # 4
c、str.rfind():倒序字串查詢函式
函式原型:
str.rfind( substr [, pos_start [,pos_ end ] ])
返回str中最後出現的substr的第一個字母的標號,如果str中沒有substr則返回-1,也就是說從右邊算起的第一次出現的substr的首字母標號。
引數說明:
str:代表原字串
substr:代表要查詢的字串
pos_start:代表查詢的開始位置,預設是從下標0開始查詢
pos_end:代表查詢的結束位置
例子:
'adsfddf'.rfind('d') # 5
d、str.rindex():倒序字串查詢函式
rindex()函式類似於rfind()函式,在Python中也是在字串中倒序查詢子串最後一次出現的位置,跟rfind()不同的是,未找到則丟擲異常。
函式原型:
str.rindex(substr [, pos_start, [ pos_end ] ] )
引數說明:
str:代表原字串
substr:代表要查詢的字串
pos_start:代表查詢的開始位置,預設是從下標0開始查詢
pos_end:代表查詢的結束位置
例子:
'adsfddf'.rindex('d') # 5
e、使用re模組進行查詢和替換:
函式 | 說明 |
---|---|
re.match(pat, s) | 只從字串s的頭開始匹配,比如(‘123’, ‘12345’)匹配上了,而(‘123’,’01234’)就是沒有匹配上,沒有匹配上返回None,匹配上返回matchobject |
re.search(pat, s) | 從字串s的任意位置都進行匹配,比如(‘123’,’01234’)就是匹配上了,只要s只能存在符合pat的連續字串就算匹配上了,沒有匹配上返回None,匹配上返回matchobject |
re.sub(pat,newpat,s) | re.sub(pat,newpat,s) 對字串中s的包含的所有符合pat的連續字串進行替換,如果newpat為str,那麼就是替換為newpat,如果newpat是函式,那麼就按照函式返回值替換。sub函式兩個有預設值的引數分別是count表示最多隻處理前幾個匹配的字串,預設為0表示全部處理;最後一個是flags,預設為0 |
f、使用replace()進行替換:
基本用法:物件.replace(rgExp,replaceText,max)
其中,rgExp和replaceText是必須要有的,max是可選的引數,可以不加。
rgExp是指正則表示式模式或可用標誌的正則表示式物件,也可以是 String 物件或文字;
replaceText是一個String 物件或字串文字;
max是一個數字。
對於一個物件,在物件的每個rgExp都替換成replaceText,從左到右最多max次。
s1='hello world'
s1.replace('world','liming')
97.用Python匹配HTML tag的時候,<.> 和 <.?> 有什麼區別
第一個代表貪心匹配,第二個代表非貪心;
?在一般正則表示式裡的語法是指的"零次或一次匹配左邊的字元或表示式"相當於{0,1}
而當?字尾於*,+,?,{n},{n,},{n,m}之後,則代表非貪心匹配模式,也就是說,儘可能少的匹配左邊的字元或表示式,這裡是儘可能少的匹配.(任意字元)
所以:第一種寫法是,儘可能多的匹配,就是匹配到的字串儘量長,第二中寫法是儘可能少的匹配,就是匹配到的字串儘量短。
比如<tag>tag>tag>end,第一個會匹配<tag>tag>tag>,第二個會匹配<tag>。
98.正則表示式貪婪與非貪婪模式的區別?
貪婪模式:
定義:正則表示式去匹配時,會盡量多的匹配符合條件的內容
識別符號:+,?,*,{n},{n,},{n,m}
匹配時,如果遇到上述識別符號,代表是貪婪匹配,會盡可能多的去匹配內容
非貪婪模式:
定義:正則表示式去匹配時,會盡量少的匹配符合條件的內容 也就是說,一旦發現匹配符合要求,立馬就匹配成功,而不會繼續匹配下去(除非有g,開啟下一組匹配)
識別符號:+?,??,*?,{n}?,{n,}?,{n,m}?
可以看到,非貪婪模式的識別符號很有規律,就是貪婪模式的識別符號後面加上一個?
參考文章:https://dailc.github.io/2017/07/06/regularExpressionGreedyAndLazy.html
99.寫出開頭匹配字母和下劃線,末尾是數字的正則表示式?
s1='_aai0efe00'
res=re.findall('^[a-zA-Z_]?[a-zA-Z0-9_]{1,}\d$',s1)
print(res)
100.正則表示式操作
101.請匹配出變數A 中的json字串。
102.怎麼過濾評論中的表情?
思路:主要是匹配表情包的範圍,將表情包的範圍用空替換掉
import re
pattern = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]')
pattern.sub('',text)
103.簡述Python裡面search和match的區別
match()函式只檢測字串開頭位置是否匹配,匹配成功才會返回結果,否則返回None;
search()函式會在整個字串內查詢模式匹配,只到找到第一個匹配然後返回一個包含匹配資訊的物件,該物件可以通過呼叫group()方法得到匹配的字串,如果字串沒有匹配,則返回None。
104.請寫出匹配ip的Python正則表示式
105.Python裡match與search的區別?
見103題