最近在做LeetCode的算法題,本來把知識點寫在一起了。但是很不直觀,所以單獨拿出來寫了。
5. Python 3 中的 map() 函數與 reduce() 函數
知識點複習
1. LeetCode 中的 Python 3 函數說明:
def removeDuplicates(self, nums: List[int]) -> int:
- nums: List[int]:形參名字爲 nums,參數類型爲 List (列表)
- -> int:返回參數類型爲 int
2. Python 3 函數
2.1 函數參數爲對象
在 python 中,strings, tuples, 和 numbers 是不可更改(immutable)的對象,而 list,dict 等則是可以修改(mutable)的對象。
-
不可變對象:變量賦值 a=5 後再賦值 a=10,這裏實際是新生成一個 int 值對象 10,再讓 a 指向它,而 5 被丟棄,不是改變a的值,相當於新生成了a。
-
可變對象:變量賦值 la=[1,2,3,4] 後再賦值 la[2]=5 則是將 list la 的第三個元素值更改,本身la沒有動,只是其內部的一部分值被修改了。
2.2 函數參數傳遞
在 python 中,類型屬於對象,變量是沒有類型的,僅僅是一個對象的引用(一個指針)。可分爲不可變類型和可變類型。
-
不可變類型:類似 c++ 的值傳遞,如 整數、字符串、元組。如fun(a),傳遞的只是a的值,沒有影響a對象本身。比如在 fun(a)內部修改 a 的值,只是修改另一個複製的對象,不會影響 a 本身。
-
可變類型:類似 c++ 的引用傳遞,如 列表,字典。如 fun(la),則是將 la 真正的傳過去,修改後fun外部的la也會受影響。
2.3 函數參數類型
- 必須參數:必需參數須以正確的順序傳入函數。調用時的數量必須和聲明時的一樣。
def function(para1, para2): # 參數沒有限制,但是調用時順序不能錯。
print(para1)
print(para2)
function("PARAMETER", 10010) # 如果調用時參數個數不對會報錯
- 關鍵字參數:關鍵字參數和函數調用關係緊密,函數調用使用關鍵字參數來確定傳入的參數值。使用關鍵字參數允許函數調用時參數的順序與聲明時不一致,因爲 Python 解釋器能夠用參數名匹配參數值。
def function(para1, para2): # 參數沒有限制,調用時加上參數名字,順序可以不同。
print(para1)
print(para2)
function(para2="PARAMETER", para1=10010) # 如果調用時參數個數不對會報錯
- 默認參數:調用函數時,如果沒有傳遞參數,則會使用默認參數。
def function(para1, para2=10086): # 默認參數類型已定,若要改變默認參數值,類型要一致。
print(para1)
print(para2)
function("PARAMETER1") # 可以不調用默認參數
- 不定長度參數:一個函數能處理比當初聲明時更多的參數。
def function1(para1, para2=10086, *var_args): # 一個“*”的參數形式爲元組。
print(para1)
print(para2)
if len(var_args) != 0:
for item in var_args:
print(item)
def function2(para1, para2=10086, **var_args): # 兩個“*”的參數形式爲字典
print(para1)
print(para2)
print(var_args)
def function3(para1, para2=10086, *, para3): # 函數聲明時,可以只寫“*”,但是後面的參數必需以關鍵詞參數形式寫入。
print(para1)
print(para2)
print(var_args)
function1("PARAMETER1") # 至少保證必需參數要在
function2("PARAMETER1", a=100, b=10) # 字典形式寫參數
function1("PARAMETER1", a=100, para3=10086) # “*”後的以關鍵字形式寫入
- 匿名函數:使用 lambda 來創建匿名函數。
- lambda 只是一個表達式,函數體比 def 簡單很多。
- lambda的主體是一個表達式,而不是一個代碼塊。僅僅能在lambda表達式中封裝有限的邏輯進去。
- lambda 函數擁有自己的命名空間,且不能訪問自己參數列表之外或全局命名空間裏的參數。
- 雖然lambda函數看起來只能寫一行,卻不等同於C或C++的內聯函數,後者的目的是調用小函數時不佔用棧內存從而增加運行效率。
multiply = lambda para1, para2: para1 * para2 # lambda形式->參數:表達式
print(multiply(10086, 10010)) # 調用時直接寫就行
- Python3.8 新增了一個函數形參語法“/”用來指明函數形參必須使用指定位置參數,不能使用關鍵字參數的形式。
def function(a, b, /, c, d, *, e, f):
# 形參 a 和 b 必須使用指定位置參數,c 或 d 可以是位置形參或關鍵字形參,而 e 或 f 要求爲關鍵字形參
print(a, b, c, d, e, f)
function(10, 20, 30, d=40, e=50, f=60)
3. Python 中的 set 無序不重複集合
集合(set)是一個無序的不重複元素序列。
可以使用大括號 { } 或者 set() 函數創建集合,注意:創建一個空集合必須用 set() 而不是 { },因爲 { } 是用來創建一個空字典。
創建格式:
parame = {value01,value02,...}
或者
set(value)
4. Python 中的 位運算符
運算符 | 描述 | 實例 |
& | 按位與運算符:參與運算的兩個值,如果兩個相應位都爲1,則該位的結果爲1,否則爲0 | (a & b) 輸出結果 12 ,二進制解釋: 0000 1100 |
| | 按位或運算符:只要對應的二個二進位有一個爲1時,結果位就爲1。 | (a | b) 輸出結果 61 ,二進制解釋: 0011 1101 |
~ | 按位取反運算符:對數據的每個二進制位取反,即把1變爲0,把0變爲1。~x 類似於 -x-1 | (~a ) 輸出結果 -61 ,二進制解釋: 1100 0011, 在一個有符號二進制數的補碼形式 |
^ | 按位異或運算符:當兩對應的二進位相異時,結果爲1 | (a ^ b) 輸出結果 49 ,二進制解釋: 0011 0001 |
<< | 左移動運算符:運算數的各二進位全部左移若干位,由"<<"右邊的數指定移動的位數,高位丟棄,低位補0。 | a << 2 輸出結果 240 ,二進制解釋: 1111 0000 |
>> | 右移動運算符:把">>"左邊的運算數的各二進位全部右移若干位,">>"右邊的數指定移動的位數 | a >> 2 輸出結果 15 ,二進制解釋: 0000 1111 |
其中a=60=0011 1100,b=13=0000 1101。
5. Python 3 中的 map() 函數與 reduce() 函數
map() 函數:
- 函數形式:map(function(), iterable, ...)
- 解釋:map相當於映射,針對迭代器中的每一個元素分別操作,逐一映射,最終得到長度不變的結果。
reduce() 函數:
- 函數形式:reduce(function(), iterable[, initializer])
- 解釋:reduce相當於歸於,序列中相鄰兩個元素逐次進入函數計算,最後得到一個返回值。
- Python 3 中把 reduce() 放入 functools包中
6. Python 3 中內置函數函數
字符串操作時所需要的函數:
- python 3 中字符轉ASCII碼函數:ord(char)
- python 3 中ASCII碼轉字符函數:chr(int)
- 從左到右讀讀取字符串尋找對應字符str:find(str, begin=0, end=len(s))
- 從右到左讀讀取字符串尋找對應字符str:rfind(str, begin=0, end=len(s))
- 截掉字符串左邊的空格或指定字符:lstrip()
- 刪除字符串字符串末尾的空格:rstrip()
7. Python 3 中的解包
解包在英文裏叫做 Unpacking,是將容器裏面的元素逐個取出來賦值給其他變量。Python 中的解包是自動完成的。要注意的是,解包時賦值的變量個數應該和容器內的元素的個數一致。
>>> a, b, c = [1, 2, 3]
>>> a
1
>>> b
2
>>> c
3
容器可以是 list, dictionary, set, truple, string。但對於dictionary,取出來的只有key,value並沒有。
其實多變量的賦值,以及常用的變量交換都是解包的操作。
當解包的變量個數與容器中的元素個數不同時,可以這麼寫
>>> a, b, *c = [1,2,3,4]
>>> a
1
>>> b
2
>>> c
[3, 4]
# ******************************
>>> a, *b, c = [1,2,3,4]
>>> a
1
>>> b
[2, 3]
>>> c
4
函數被調用的時候,使用星號 *
解包一個可迭代對象作爲函數的參數。
字典對象,可以使用 **
星號,解包之後將作爲關鍵字參數傳遞給函數。
舉例:
>>> def func(a,b,c):
... print(a,b,c)
...
>>> func(1,2,3)
1 2 3
>>> func(*[1,2,3])
1 2 3
>>> func(*(1,2,3))
1 2 3
>>> func(*"abc")
a b c
>>> func(*{"a":1,"b":2,"c":3})
a b c
>>> func(**{"a":1,"b":2,"c":3})
1 2 3
一個
*
符號只是將字典當作一般的容器,只取除了key,而不考慮value。兩個
**
時作用的對象是字典對象,它會自動解包成關鍵字參數 key=value 的格式,比如 a=1, b=2, c=3。而函數的形參就是a, b, c。倘若字典的key不是a, b, c則會報錯,說輸入不是期望的參數。
在 Python 3.5 之後可以允許多個解包操作同時在一個函數中。
>>> func(*[1, 2], **{'c':5})
1 2 5
>>> func(*[1, 2], 3)
1 2 3
解包還有用於生成list等快捷操作。
>>> *range(0, 5), 5 # 生成truple
(0, 1, 2, 3, 4, 5)
>>> [*range(0, 5), 5, 6] # 生成list
[0, 1, 2, 3, 4, 5, 6]
>>> {*range(0, 5), 5, 6, 7} # 生成set
{0, 1, 2, 3, 4, 5, 6, 7}
>>> {'x': 1, **{'y': 2}} # 生成dictionary
{'x': 1, 'y': 2}
>>> list1 = [1,2,3]
>>> list2 = range(3,6) # range 與 list 不能直接相加
>>> [*list1, *list2]
[1, 2, 3, 3, 4, 5]
8 Python 3 中正則表達
這部分內容比較多,可以直接參看 Python3 正則表達式
大概寫一下需要用到的函數
re.match函數
- re.match(pattern, string, flags=0);
- flags:標誌位,用於控制正則表達式的匹配方式,如:是否區分大小寫,多行匹配等等。
- 嘗試從字符串的起始位置匹配一個模式,如果不是起始位置匹配成功的話,match()就返回none。
re.searc函數
- re.search(pattern, string, flags=0),同re.match函數
- 掃描整個字符串並返回第一個成功的匹配。
在匹配成功後,上面的兩個函數都會返回一個對象,我們可以使用group(num) 或 groups() 匹配對象函數來獲取匹配表達式。
import re
line = "Cats are smarter than dogs"
# .* 表示任意匹配除換行符(\n、\r)之外的任何單個或多個字符
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
# 輸出如下
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
re.match 與 re.search 的區別
re.match 只匹配字符串的開始,如果字符串開始不符合正則表達式,則匹配失敗,函數返回 None,而 re.search 匹配整個字符串,直到找到一個匹配。
re.sub 函數
- re.sub(pattern, repl, string, count=0, flags=0);
- repl : 替換的字符串,也可爲一個函數。
- count : 模式匹配後替換的最大次數,默認 0 表示替換所有的匹配。
- 用於替換字符串中的匹配項。
re.compile 函數
- re.compile(pattern[, flags])
- compile 函數用於編譯正則表達式,生成一個正則表達式( Pattern )對象,供 match() 和 search() 這兩個函數使用。
re.findall 函數
- re.findall(string[, pos[, endpos]])
- pos 可選參數,指定字符串的起始位置,默認爲 0。
- endpos 可選參數,指定字符串的結束位置,默認爲字符串的長度。
- 在字符串中找到正則表達式所匹配的所有子串,並返回一個列表,如果沒有找到匹配的,則返回空列表。
re.finditer 函數
- re.finditer(pattern, string, flags=0)
- 和 findall 類似,在字符串中找到正則表達式所匹配的所有子串,並把它們作爲一個迭代器返回。
re.split 函數
- re.split(pattern, string[, maxsplit=0, flags=0])
- 分隔次數,maxsplit=1 分隔一次,默認爲 0,不限制次數。
- split 方法按照能夠匹配的子串將字符串分割後返回列表。
正則表達式修飾符 - 可選標誌
多個標誌可以通過按位 OR(|) 它們來指定。如 re.I | re.M 被設置成 I 和 M 標誌:
修飾符 | 描述 |
---|---|
re.I | 使匹配對大小寫不敏感 |
re.L | 做本地化識別(locale-aware)匹配 |
re.M | 多行匹配,影響 ^ 和 $ |
re.S | 使 . 匹配包括換行在內的所有字符 |
re.U | 根據Unicode字符集解析字符。這個標誌影響 \w, \W, \b, \B. |
re.X | 該標誌通過給予你更靈活的格式以便你將正則表達式寫得更易於理解。 |
正則表達式模式
模式字符串使用特殊的語法來表示一個正則表達式:
字母和數字表示他們自身。一個正則表達式模式中的字母和數字匹配同樣的字符串。
多數字母和數字前加一個反斜槓時會擁有不同的含義。
標點符號只有被轉義時才匹配自身,否則它們表示特殊的含義。
反斜槓本身需要使用反斜槓轉義。
由於正則表達式通常都包含反斜槓,所以你最好使用原始字符串來表示它們。模式元素(如 r'\t',等價於 \\t )匹配相應的特殊字符。
下表列出了正則表達式模式語法中的特殊元素。如果你使用模式的同時提供了可選的標誌參數,某些模式元素的含義會改變。
模式 | 描述 |
---|---|
^ | 匹配字符串的開頭 |
$ | 匹配字符串的末尾。 |
. | 匹配任意字符,除了換行符,當re.DOTALL標記被指定時,則可以匹配包括換行符的任意字符。 |
[...] | 用來表示一組字符,單獨列出:[amk] 匹配 'a','m'或'k' |
[^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
re* | 匹配0個或多個的表達式。 |
re+ | 匹配1個或多個的表達式。 |
re? | 匹配0個或1個由前面的正則表達式定義的片段,非貪婪方式 |
re{ n} | 匹配n個前面表達式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的兩個o。 |
re{ n,} | 精確匹配n個前面表達式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等價於"o+"。"o{0,}"則等價於"o*"。 |
re{ n, m} | 匹配 n 到 m 次由前面的正則表達式定義的片段,貪婪方式 |
a| b | 匹配a或b |
(re) | 匹配括號內的表達式,也表示一個組 |
(?imx) | 正則表達式包含三種可選標誌:i, m, 或 x 。隻影響括號中的區域。 |
(?-imx) | 正則表達式關閉 i, m, 或 x 可選標誌。隻影響括號中的區域。 |
(?: re) | 類似 (...), 但是不表示一個組 |
(?imx: re) | 在括號中使用i, m, 或 x 可選標誌 |
(?-imx: re) | 在括號中不使用i, m, 或 x 可選標誌 |
(?#...) | 註釋. |
(?= re) | 前向肯定界定符。如果所含正則表達式,以 ... 表示,在當前位置成功匹配時成功,否則失敗。但一旦所含表達式已經嘗試,匹配引擎根本沒有提高;模式的剩餘部分還要嘗試界定符的右邊。 |
(?! re) | 前向否定界定符。與肯定界定符相反;當所含表達式不能在字符串當前位置匹配時成功。 |
(?> re) | 匹配的獨立模式,省去回溯。 |
\w | 匹配數字字母下劃線 |
\W | 匹配非數字字母下劃線 |
\s | 匹配任意空白字符,等價於 [\t\n\r\f]。 |
\S | 匹配任意非空字符 |
\d | 匹配任意數字,等價於 [0-9]。 |
\D | 匹配任意非數字 |
\A | 匹配字符串開始 |
\Z | 匹配字符串結束,如果是存在換行,只匹配到換行前的結束字符串。 |
\z | 匹配字符串結束 |
\G | 匹配最後匹配完成的位置。 |
\b | 匹配一個單詞邊界,也就是指單詞和空格間的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
\B | 匹配非單詞邊界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
\n, \t, 等。 | 匹配一個換行符。匹配一個製表符, 等 |
\1...\9 | 匹配第n個分組的內容。 |
\10 | 匹配第n個分組的內容,如果它經匹配。否則指的是八進制字符碼的表達式。 |