1. 切片
1a = "hello world"
2print(a[::-1])
3# dlrow olleh
2. 原地交換 / 同時(shí)賦值
1a = 1
2b = 2
3print(f"First: {a, b}")
4# First: (1, 2)
5
6a, b = b, a + 2
7print(f"Second: {a, b}")
8# Second: (2, 3)
9
10a, b* = 1, 2, 3
11print(a, b)
12# 1 [2, 3]
3. 列表和元組
1import sys
2
3a = [1, 2, 3, 4, 5]
4b = (1, 2, 3, 4, 5)
5
6print(f"List size: {sys.getsizeof(a)} bytes")
7print(f"Tuple size: {sys.getsizeof(b)} bytes")
8
9'''
10List size: 104 bytes
11Tuple size: 80 bytes
12'''
列表是可變的,元組不可變。在列表中,額外的內(nèi)存會(huì)被分配以防我們擴(kuò)展,被稱為動(dòng)態(tài)內(nèi)存分配。而在不希望更改數(shù)據(jù)的場(chǎng)景中,出于內(nèi)存方面原因,元組數(shù)據(jù)結(jié)構(gòu)應(yīng)該優(yōu)先于列表,元組也比列表快。
4. 生成器
1a = [x * 2 for x in range(10)]
2b = (x * 2 for x in range(10))
3
4print(a)
5print(b)
6
7"""
8[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
9
列表解析是從另一個(gè)可迭代對(duì)象創(chuàng)建列表的Python方式--它比使用for循環(huán)快得多。但是如果不小心將方括號(hào)從[]改為(),將得到一個(gè)生成器對(duì)象。每個(gè)元素只在請(qǐng)求時(shí)使用,也就是惰性計(jì)算,使用生成器的主要好處是,它使用的內(nèi)存較少,因?yàn)檎麄€(gè)序列不是一次構(gòu)建的。
5. 混疊
1a = [1, 2, 3, 4 ,5]
2b = a
3
4b[4] = 7
5
6print(id(a))
7print(id(b))
8print(a)
9
10"""
112278459070720
122278459070720
13[1, 2, 3, 4, 7]
14"""
Python是一種面向?qū)ο蟮?a target="_blank">編程語(yǔ)言--一切都是對(duì)象。因此,將對(duì)象分配給標(biāo)識(shí)符就是創(chuàng)建對(duì)該對(duì)象的引用。
當(dāng)我們將一個(gè)標(biāo)識(shí)符賦給另一個(gè)標(biāo)識(shí)符時(shí),我們最終得到引用同一對(duì)象的兩個(gè)標(biāo)識(shí)符。這是一個(gè)稱為混疊的概念。更改一個(gè)別名將影響另一個(gè)別名。有時(shí)候,這種行為是我們想要的,但通常,它讓我們措手不及。
一種解決方法是在使用可變對(duì)象時(shí)避免別名。另一個(gè)解決方案是創(chuàng)建原始對(duì)象的克隆,而不是引用。
創(chuàng)建克隆最直接的方法是利用切片:
1b = a[:]
6. 'not' 操作符
1a = []
2print(not a)
3
4"""
5True
6"""
下一個(gè)Python技巧是使用not操作符檢查數(shù)據(jù)結(jié)構(gòu)是否為空的最簡(jiǎn)單方法。Python內(nèi)置的not是一個(gè)邏輯運(yùn)算符,如果表達(dá)式不為真,它返回True,否則返回False
另一種使用方式是在if語(yǔ)句中:
1if not a:
2 # do something...
7. F-字符串
1first_name = "John"
2age = 19
3
4print(f"Hi, I'm {first_name} and I'm {age} years old!")
5
6"""
7Hi, I'm John and I'm 19 years old!
8"""
也可以使用:
1print("Hi, I'm {} and I'm {} years old!".format(first_name, age))
8. print函數(shù)中'end'參數(shù)
1a = ["english", "french", "spanish", "german", "twi"]
2for language in a:
3 print(language, end=" ")
4
5"""
6english french spanish german twi
7"""
使用print語(yǔ)句而不定義任何可選參數(shù)是很常見(jiàn)的。
我們可以更改的一個(gè)可選參數(shù)是end。end參數(shù)指定在調(diào)用print語(yǔ)句結(jié)束時(shí)應(yīng)顯示的內(nèi)容。
end的默認(rèn)值是“\\n”,它告訴Python開(kāi)始一個(gè)新行。在上面的代碼中,我們將其更改為空格。因此,返回的輸出中列表的所有元素都打印在同一行上。
9. 追加數(shù)據(jù)到元組
1a = (1, 2, [1, 2, 3])
2a[2].append(4)
3print(a)
4
5"""
6(1, 2, [1, 2, 3, 4])
7"""
我們已經(jīng)知道元組是不可變的。嘗試更改元組的狀態(tài)將引發(fā)TypeError。但是,如果您將元組對(duì)象看作是綁定到不能更改的對(duì)象的名稱序列,元組的前兩個(gè)元素是整數(shù)--它們是不可變的。元組的最后一個(gè)元素是一個(gè)列表,在Python中是一個(gè)可變對(duì)象。
如果我們認(rèn)為列表只是序列中的另一個(gè)名稱,它綁定到一個(gè)不能更改的對(duì)象,那么我們會(huì)意識(shí)到列表仍然可以從元組中修改。
10. 合并字典
1a = {"a": 1, "b": 2}
2b = {"c": 3, "d": 4}
3
4a_and_b = a | b
5print(a_and_b)
6
7"""
8{"a": 1, "b": 2, "c": 3, "d": 4}
9"""
在Python 3.9及更高版本中,可以使用 |。關(guān)于這個(gè)特殊的Python技巧,除了它是一個(gè)可讀性更強(qiáng)的解決方案之外,沒(méi)有什么可說(shuō)的!
11. 三元運(yùn)算符 / 條件表達(dá)式
1condition = True
2name = "John" if condition else "Doe"
3
4print(name)
5
6"""
7John
8"""
12. 從列表中去掉重復(fù)項(xiàng)
1a = [1, 1, 2, 3, 4, 5, 5, 5, 6, 7, 2, 2]
2print(list(set(a)))
3
4"""
5[1, 2, 3, 4, 5, 6, 7]
6"""
從列表中刪除重復(fù)元素的最簡(jiǎn)單方法是將列表轉(zhuǎn)換為集合(如果愿意,然后再轉(zhuǎn)換回列表)。
集合和列表之間的關(guān)鍵區(qū)別是集合不能包含重復(fù)項(xiàng)。
13. 單獨(dú)下劃線
1>>> print(_)
2Traceback (most recent call last):
3 File "
下劃線(_)是Python中的合法的標(biāo)識(shí)符,因此,可以使用它來(lái)引用對(duì)象。但強(qiáng)調(diào)還有另一個(gè)責(zé)任:以存儲(chǔ)最后的結(jié)果。文檔指出,“交互式解釋器使最后一次求值的結(jié)果在變量中可用?!?/p>
因?yàn)槲覀冊(cè)诘谝恍姓{(diào)用對(duì)象之前沒(méi)有給它賦值下劃線,所以我們得到了一個(gè)錯(cuò)誤。但是,當(dāng)我們計(jì)算1 + 2的輸出時(shí),交互式解釋器為我們將結(jié)果存儲(chǔ)在_中。
14. 用下劃線表示忽略的值
1for _ in range(100):
2 print("The index doesn't matter")
3
4"""
5The index doesn't matter
6The index doesn't matter
7...
8"""
我們也可以用它來(lái)表示我們不關(guān)心的對(duì)象,或者在程序的后面不會(huì)使用的對(duì)象。
15. 尾部下劃線
1list_ = [0, 1, 2, 3, 4]
2global_ = "Hi there"
繼續(xù)前兩個(gè)技巧,Python的下劃線(_)用法,它的另一個(gè)目的是避免與Python關(guān)鍵字沖突。PEP8提到尾部下劃線()應(yīng)該按照約定使用,以避免與Python關(guān)鍵字沖突。它還指出,“通常最好附加一個(gè)尾隨下劃線,而不是使用縮寫(xiě)?!币虼薼ist_優(yōu)于lst。
16. 前置下劃線
1class Example:
2 def __init__(self):
3 self._internal = 2
4 self.external = 20
你經(jīng)常會(huì)發(fā)現(xiàn)有經(jīng)驗(yàn)的Python程序員傾向于在標(biāo)識(shí)符或方法名前面加上下劃線--這是有原因的。
標(biāo)識(shí)符或方法前面的下劃線具有隱藏的含義:此變量或方法僅用于內(nèi)部使用。本質(zhì)上,它是對(duì)其他程序員的免責(zé)聲明,這些程序員在PEP 8中已經(jīng)定義,但Python沒(méi)有強(qiáng)制執(zhí)行。因此,前置下劃線是弱指示符。
17. 下劃線用于數(shù)字顯示
1number = 1_500_000
2print(number)
3
4"""
515000000
6"""
我們可以使用下劃線的另一種方式是作為整數(shù)、浮點(diǎn)數(shù)和復(fù)數(shù)常量中數(shù)字分組的可視分隔符--這是在Python 3.6中引入的。這樣做的目的是為了提高長(zhǎng)文本的可讀性。
18. name == " main "
1if __name__ == "__main__":
2 print("Read on to understand what is going on when you do this.")
3
4"""
5print("Read on to understand what is going on when you do this.")
6"""
你很有可能在幾個(gè)Python程序中見(jiàn)過(guò)這種語(yǔ)法;Python使用一個(gè)特殊的名稱__main__,如果運(yùn)行的Python文件是主程序,則將其設(shè)置為一個(gè)名為_(kāi)_name__的標(biāo)識(shí)符。如果我們決定將當(dāng)前顯示的模塊導(dǎo)入到另一個(gè)模塊(Python文件)中并運(yùn)行該文件,則代碼中表達(dá)式的值將為false。這是因?yàn)楫?dāng)我們從另一個(gè)模塊導(dǎo)入時(shí),__name__標(biāo)識(shí)符被設(shè)置為模塊(Python文件)的名稱。
19. setdefault 方法
1import pprint
2
3text = "It's the first of April. It's still cold in the UK. But I'm going to the museum so it should be a wonderful day"
4
5counts = {}
6for word in text.split():
7 counts.setdefault(word, 0)
8 counts[word] += 1
9
10pprint.pprint(counts)
11
12"""
13{'April.': 1,
14"It's": 2,
15'UK.': 1,
16...
17'still': 1,
18'the': 3,
19'to': 1,
20'wonderful': 1}
21"
22
可能會(huì)碰到這種需求,檢查元素是否存在一個(gè)字典中,存在當(dāng)前值加1,不存在添加當(dāng)前值并設(shè)置其為1,看起來(lái)如下:
1counts = {}
2for word in text.split():
3 if word in counts:
4 counts[word] += 1
5 else:
6 counts[word] = 1
更簡(jiǎn)潔的方法是在dictionary對(duì)象上使用setdefault()方法。
傳遞給方法的第一個(gè)參數(shù)是我們要檢查的鍵。傳遞的第二個(gè)參數(shù)是當(dāng)鍵在字典中不存在時(shí)設(shè)置鍵的值-如果鍵存在,則方法將返回鍵值。因此,不會(huì)對(duì)其進(jìn)行更改。
20. 正則匹配
1import re
2
3number = re.compile(r"(0?)(\\+44)?\\d(10)")
4num_1 = number.search("My number is +447999999999")
5num_2 = number.search("My number is 07999999999")
6
7print(num_1.group())
8print(num_2.group())
9
10"""
11'+447999999999'
12'07999999999'
13"""
21. 正則表達(dá)式管道‘|’使用
1import re
2
3heros = re.compile(r"Super(man|woman|human)")
4
5h1 = heros.search("This will find Superman")
6h2 = heros.search("This will find Superwoman")
7h3 = heros.search("This will find Superhuman")
8
9print(h1.group())
10print(h2.group())
11print(h3.group())
12
13"""
14Superman
15Superwoman
16Superhuman
17"""
正則表達(dá)式有一個(gè)特殊字符,稱為管道(|),它允許您匹配許多表達(dá)式中的一個(gè),并且它們可以在任何地方使用。
22. print函數(shù)中‘sep’參數(shù)
1day = "04"
2month = "10"
3year = "2023"
4
5print(day, month, year)
6print(day, month, year, sep = "")
7print(day, month, year, sep = ".")
8
9"""
1004 10 2023
1104/10/2023
1204.10.2023
13"""
sep參數(shù)是print()函數(shù)中的一個(gè)可選參數(shù),它允許我們指定在包含多個(gè)對(duì)象時(shí)應(yīng)該如何分隔對(duì)象。
默認(rèn)情況下是用空格分隔它們。
23. Lambda 函數(shù)
1def square(num:int) -> int:
2 return num ** 2
3
4print(f"Function call: {square(4)}")
5"""
6Function call: 16
7"""
8
9square_lambda = lambda x: x**2
10print(f"Lambda function: {square_lambda(4)}")
11"""
12Lambda functional: 16
13"""
本質(zhì)上,lambda關(guān)鍵字允許我們?cè)谝恍兄袆?chuàng)建小的、受限的、匿名的函數(shù)。它們的行為與使用def關(guān)鍵字聲明的常規(guī)函數(shù)相同,只是這些函數(shù)沒(méi)有名稱。
24. swapcase方法
1string = "SoMe RaNDoM sTriNg"
2print(string.swapcase())
3
4"""
5sOmE rAndOm StRInG
6"""
swapcase()方法應(yīng)用于字符串對(duì)象,允許我們?cè)谝恍写a中將大寫(xiě)字母改為小寫(xiě)字母,反之亦然。swapcase()方法的用例并不多,但了解一下還是很不錯(cuò)的。
25. isalnum方法
1password = "ABCabc123"
2print(password.isalnum())
3
4"""
5True
6"""
假設(shè)我們正在創(chuàng)建一個(gè)程序,要求用戶輸入密碼,但密碼必須是數(shù)字和字母的組合。我們可以通過(guò)調(diào)用string實(shí)例上的isalnum()在一行代碼中完成此操作。
該方法檢查所有字符是否都是字母表(A-Za-z)和數(shù)字(0 - 9)的一部分??崭窕蚍?hào)(!# %$&?等等)將返回False。
26. 異常處理
1def get_ration(x:int, y:int) -> int:
2 try:
3 ratio = x/y
4 except: ZeroDivisionError:
5 y = y + 1
6 ratio = x/y
7 return ratio
8
9print(get_ratio(x=400, y=0))
10
11"""
12400.0
13"""
Python程序在遇到錯(cuò)誤時(shí)終止。
有時(shí)候,我們不希望出現(xiàn)這種行為,比如當(dāng)最終用戶與我們的代碼交互時(shí)。如果我們的代碼在這種情況下過(guò)早終止,會(huì)有多糟糕?
關(guān)于如何處理這種例外情況,有幾種思路。大多數(shù)Python程序員通常都認(rèn)為請(qǐng)求原諒比獲得許可更容易。這意味著它們更愿意通過(guò)提供能夠處理異常的周圍上下文來(lái)捕獲引發(fā)的錯(cuò)誤。這種想法背后的思想是,浪費(fèi)時(shí)間試圖防范所有各種例外情況是沒(méi)有意義的。
但這只有在問(wèn)題發(fā)生后有一種處理機(jī)制的情況下才成立。
27. 比較兩個(gè)的列表差異
1list_1 = [1, 3, 5, 7, 8]
2list_2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
3
4solution_1 = list(set(list_2) - set(list_1))
5solution_2 = list(set(list_1) ^ set(list_2))
6solution_3 = list(set(list_1).symmetric_difference(set(list_2)))
7
8print(f"Solution 1: {solution_1}")
9print(f"Solution 2: {solution_2}")
10print(f"Solution 3: {solution_3}")
11
12"""
13Solution 1: [9, 2, 4, 6]
14Solution 2: [2, 4, 6, 9]
15Solution 3: [2, 4, 6, 9]
16"""
這里有三種不同的方法來(lái)比較Python中兩個(gè)列表之間的差異。
注意:除非你知道list_1是list_2的子集,否則solution 1和其他兩個(gè)solution是不一樣的。
28. Args & Kwargs
1def some_function(*args, **kwargs):
2 print(f"Args: {args}")
3 print(f"Kwargs: {kwargs}")
4
5some_function(1, 2, 3, a=4, b=5, c=6)
6
7"""
8Args: (1, 2, 3)
9Kwargs: {'a': 4, 'b': 5, 'c': 6}
10"""
當(dāng)我們不知道函數(shù)應(yīng)該包含多少變量時(shí),我們使用 *args和 **kwargs作為函數(shù)的參數(shù)。參數(shù) *args允許我們?cè)诤瘮?shù)沒(méi)有關(guān)鍵字時(shí)(即:我們傳遞的參數(shù)不需要相關(guān)聯(lián)的名稱)。另一方面,kwargs參數(shù)使我們能夠向函數(shù)傳遞任意數(shù)量的關(guān)鍵字參數(shù)。
事實(shí)上,*args和 **kwargs這兩個(gè)詞并沒(méi)有那么神奇:真正的魔力在于星號(hào)()。這意味著我們可以在星號(hào)后面使用任何單詞,但是使用args和kwargs是常見(jiàn)的做法。
29. 省略號(hào)
1print(...)
2
3"""
4Ellipsis
5"""
6
7def some_function():
8 ...
9
10# Alternative solution
11def another_function():
12 pass
省略號(hào)是一個(gè)Python對(duì)象,可以通過(guò)提供三個(gè)點(diǎn)(…)的序列來(lái)調(diào)用它?;蛘哒{(diào)用對(duì)象本身(省略號(hào))。
它最值得注意的用法是訪問(wèn)NumPy中的多維數(shù)組并對(duì)其進(jìn)行切片,例如:
1import numpy as np
2
3arr = np.array([[2,3], [1,2], [9,8]])
4
5print(arr[...,0])
6"""
7[2 1 9]
8"""
9print(arr[...])
10
11"""
12[[2 3]
13[1 2]
14[9 8]]
15"""
30. 列表推導(dǎo)式
1even_numbers = [x for x in range(10) if x % 2 == 0 and x != 0]
2print(even_numbers)
3
4"""
5[2, 4, 6, 8]
6"""
Python的最后一個(gè)技巧是列表解析,這是一種從另一個(gè)序列創(chuàng)建列表的優(yōu)雅方法。它們?cè)试S您執(zhí)行復(fù)雜的邏輯和過(guò)濾,就像我們?cè)谏厦娴拇a中所做的那樣。
還有其他方法可以達(dá)到同樣的目的;例如,我們可以使用lambda函數(shù),如下所示:
1even_numbers = list(filter(lambda x: x % 2 ==0 and x != 0, range(10)))
2print(even_numbers)
3"""
4[0, 2, 4, 6, 8]
5"""
評(píng)論