摘要:主要介紹元組分片序列賦值以及引用了大師為什么序列從開始計數的解釋。比如要表示如果用的方式,下界就要表示成如果一個空序列用其實是無法表示的用則可以表示成總結這一篇主要介紹元組分片序列賦值以及對為什么序列從開始計數做了摘錄。
元組這一篇是《流暢的 python》讀書筆記。主要介紹元組、分片、序列賦值以及引用了大師 Edsger W.Dijkstra為什么序列從0開始計數的解釋。
在有些python 的介紹中,元組被稱為不可變列表,這其實是不準確的,沒有完全概括元組的特點。元組除了用作不可變列表,還可以用于沒有字段名的記錄。
元組和記錄元組其實是對數據的記錄:元組中的每個元素都存放了記錄中一個字段的數據,外加這個數據的位置。
如果把元組當作一些字段的集合,數量和位置信息會變得非常重要。比如以下幾條用元組表示的記錄:
>>> lax_coordinates = (33.9425, -118.408056) # 洛杉磯國際機場的經緯度 # 東京的一些信息:市名、年份、人口、人口變化和面積 >>> city, year, pop, chg, area = ("Tokyo", 2003, 32450, 0.66, 8014)
以上這兩個元組每個位置都對應一個數據記錄。
元組拆包>>> city, year, pop, chg, area = ("Tokyo", 2003, 32450, 0.66, 8014)
這個例子中,我們把元組的數據用一條語句分別賦值給 city, year, pop, chg, area,這就是元組拆包的一個具體應用。
元組拆包可以應用到任何可迭代對象上,但是被迭代的對象窄的元素的數量必須跟接受這些元素的元組的空檔數一致。
比如:
>>> lax_coordinates = (33.9425, -118.408056) >>> latitude, longitude = lax_coordinates >>> latitude 33.9425 >>> longitude -118.408056
還可以用 * 運算符把一個可迭代對象拆開作為函數的參數:
>>> divmod(20, 8) (2, 4) >>> t = (20, 8) >>> divmode(*t) (2, 4) >>> quotient, remainder = divmode(*t) >>> quotient, remainder (2, 4)
在進行拆包是,我們可能對元組的某些值并不感興趣,這時可以用 _ 占位符處理。比如:
>>> divmode(20, 8) (2, 4) >>> _, remainder = divmode(20, 8) # 這里我們只關心第二個值 >>> remainder 4
在處理函數參數時,我們經常用*args 來表示不確定數量的參數。在python3中,這個概念被擴展到了平行賦值中:
# python 3 代碼示例 >>> a, b, *rest = range(5) >> a, b, rest (0, 1, [2, 3, 4]) # * 前綴只能用在一個變量名前,這個變量可以在其他位置 >>> a, *rest, c, d = range(5) >> a, rest, c, d (0, [1, 2], 3, 4) >>> a, b, *rest = range(2) >> a, b, rest (0, 1, [])
元組也支持嵌套拆包,比如:
>>> l = (1, 2, 3, (4, 5)) >>> a, b, c, (d, e) = l >>> d 4 >>> 5 4具名元組
元組作為記錄除了位置以外還少一個功能,那就是無法給字段命名,namedtuple解決了這個問題。
namedtuple 使用方式實例:
>>> from collecitons import namedtuple >>> city = namedtuple("City", "name country population coordinates") >>> tokyo = City("Tokyo", "JP", 36.933, (35.689722, 139.691667)) >>> tokyo.population # 可以使用字段名獲取字段信息 36.933 >>> tokyo[1] # 也可以使用位置獲取字段信息 "JP" >>> City._fields # _fields 屬性是一個包含這個類所有字段名的元組 ("name", "country", "population", "coordinates") >>> tokyo_data = ("Tokyo", "JP", 36.933, (35.689722, 139.691667)) >>> tokyo = City._make(tokyo_data) # _make() 方法接受一個可迭代對象生成這個類的實例,和 City(*tokyo_data) 作用一致 >>> tokyo._asdict() # _asdict() 把具名元組以 collections.OrderedDict 的形式呈現 OrderedDict([("name", "Tokyo"), ("country", "JP"), ("population", 36.933), ("coordinates", (35.689722, 139.691667))])
切片collections.namedtuple 是一個工廠函數,它可以用來構建一個帶字段名的元組和一個有名字的類。
namedtuple 構建的類的實例鎖消耗的內存和元組是一樣的,因為字段名都被存放在對應的類里。這個實例和普通的對象實例相比也更小一些,因為 在這個實例中,Python 不需要用 __dict__ 來存放這些實例的屬性
Python 中列表、元組、字符串都支持切片操作。
在切片和區間操作里不包含區間范圍的最后一個元素是 Python 的風格。這樣做的好處如下:
當只有最后一個位置信息時,我們可以快速看出切片和區間里有幾個元素:range(3) 和 mylist[:3] 都只返回三個元素
當氣質位置可見時,可以快速計算出切片和區間的長度,用后一個數減去第一個下標(stop-start)即可。
這樣還可以讓我們利用任意一個下標來把序列分割成不重復的兩部分,只要寫成 mylist[:x] 和 mylist[x:] 就可以。
切片除了開始和結束的下標之外還可以有第三個參數,比如:s[a:b:c],這里 c 表示取值的間隔,c 還可以為負值,負值意味著反向取值。
>>> s = "bicycle" >>> s[::3] "bye" >>> s[::-1] "elcycib" >>> s[::2] "eccb"
ac 這種用法只能作為索引或者下標在[] 中返回一個切片對象:slice(a, b, c)。對 seq[start:stop:step] 進行求值的時候,Python 會調用 seq.__getitem__(slice(start:stop:step)]。
給切片賦值如果把切片放在賦值語句的左邊,或者把它作為 del 操作的對象,我們就可以對序列進行嫁接、切除或修改操作,比如:
>>> l = list(range(10)) >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[2:5] = [20, 30] >>> l [0, 1, 20, 30, 5, 6, 7, 8, 9] >>> del l[5:7] [0, 1, 20, 30, 5, 8, 9] >>> l[3::2] = [11, 22] >>> l [0, 1, 20, 11, 5, 22, 9] >>> l[2:5] = 100 Traceback (most recent call last): file "", line 1 in TypeError: can only assign an iterable
給切片命名如果賦值的對象是一個切片,那么賦值語句的右側必須是一個可迭代對象。
如果代碼中已經出現了大量的無法直視的硬編碼切片下標,可以使用給切片命名的方式清理代碼。比如你有一段代碼要從一個記錄字符串中幾個固定位置提取出特定的數據字段 比如文件或類似格式 :
### 01234567890123456789012345678901234567890123456789012345678901234 record = "............100....513.25........" cost = int(record[20:23]) * float(record[31:37]) # 這時,可以先給切片命名,以避免大量無法理解的硬編碼下標,使代碼可讀性更強 SHARES= slice(20, 23) PRICE = slice(31, 37) cost = int(record[SHARES]) * float(record[PRICE])
slice() 函數創建了一個切片對象,可以被用在任何切片允許使用的地方,比如:
>>> items = [0, 1, 2, 3, 4, 5, 6] >>> a = slice(2, 4) >>> items[2:4] [2, 3] >>> items[a] [2, 3] >>> items[a] = [10, 11] >>> items [0, 1, 10, 11, 4, 5, 6]
如果你有一個切片對象 a,還可以調用 a.start, a.stop, a.step 來獲取更多信息,比如:
>>> a = slice(5, 50, 2) >>> a.start 5 >>> a.step 2擴展閱讀 為什么下標要從0開始
Python 里的范圍(range)和切片都不會反悔第二個下標所指的元素,計算機科學領域的大師 Edsger W.Dijkstra 在一個很短的備忘錄 Why numbering should start at zero 里對這一慣例做了說明。以下是部分關鍵說明:
為了表示出自然數的子序列,2, 3, ... , 12,不使用省略記號那三個點號,我們可以選擇4種約定方式:
a) 2 ≤ i < 13
b) 1 < i ≤ 12
c) 2 ≤ i ≤ 12
d) 1 < i < 13
是否有什么理由,使選擇其中一種約定比其它約定要好呢?是的,確實有理由。可以觀察到,a) 和 b)有個優點,上下邊界的相減得到的差,正好等于子序列的長度。另外,作為推論,下面觀察也成立:在 a),b)中,假如兩個子序列相鄰的話,其中一個序列的上界,就等于另一個序列的下界。但上面觀察,并不能讓我們從a), b)兩者中選出更好的一個。讓我們重新開始分析。
一定存在最小的自然數。假如像b)和d)那樣,子序列并不包括下界,那么當子序列從最小的自然數開始算起的時候,會使得下界進入非自然數的區域。這就比較丑陋了。所以對于下界來說,我們更應該采用≤,正如a)或c)那樣。
現在考慮,假如子序列包括上界,那么當子序列從最小的自然數開始算起,并且序列為空的時候,上界也會進入非自然數的區域。這也是丑陋的。所以,對于上界,我們更應該采用 <, 正如a)或b)那樣。因此我們得出結論,約定a)是更好的選擇。
總結比如要表示 0, 1, 2, 3 如果用 b) d) 的方式,下界就要表示成 -1 < i
如果一個空序列用 c) 其實是無法表示的,用 a) 則可以表示成 0 ≤ i < 0
這一篇主要介紹元組、分片、序列賦值以及對為什么序列從0開始計數做了摘錄。
參考鏈接Why numbering should start at zero
Why numbering should start at zero
最后,感謝女朋友支持。
歡迎關注(April_Louisa) | 請我喝芬達 |
---|---|
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/40847.html
摘要:的二進制科學計數法第位是,所以就有了下面的結果有著同樣的問題,其實正是由于這樣的存儲,在這里有了精度丟失,導致了。最大安全數字中表示最大安全數字計算結果是,即在這個數范圍內不會出現精度丟失小數除外這個數實際上是。是一個任意精度的整數。 話不多說,先上代碼 function judgeFloat(n, m) { const binaryN = n.toString(2...
摘要:希爾排序希爾排序這個名字,來源于它的發明者希爾,也稱作縮小增量排序,是插入排序的一種更高效的改進版本。我們可以發現,當區間為的時候,它使用的排序方式就是插入排序。 冒泡排序 冒泡排序無疑是最為出名的排序算法之一,從序列的一端開始往另一端冒泡(你可以從左往右冒泡,也可以從右往左冒泡,看心情),依次比較相鄰的兩個數的大小(到底是比大還是比小也看你心情)。 showImg(https://s...
摘要:在比特幣中,這種工作的目標是找到滿足某個特定要求的區塊哈希值。這個區塊哈希值就是工作結果的一個證明。因此,計算工作的目的就是為了尋找到這個證明值。例如哈希算法被廣泛用于驗證文件的一致性上。在區塊鏈中,哈希值用于保證區塊的一致性。 showImg(https://segmentfault.com/img/remote/1460000013923267?w=3500&h=2090); 最終...
摘要:在比特幣中,這種工作的目標是找到滿足某個特定要求的區塊哈希值。這個區塊哈希值就是工作結果的一個證明。因此,計算工作的目的就是為了尋找到這個證明值。例如哈希算法被廣泛用于驗證文件的一致性上。在區塊鏈中,哈希值用于保證區塊的一致性。 showImg(https://segmentfault.com/img/remote/1460000013923267?w=3500&h=2090); 最終...
閱讀 2360·2023-04-25 19:27
閱讀 3491·2021-11-24 09:39
閱讀 3906·2021-10-08 10:17
閱讀 3397·2019-08-30 13:48
閱讀 1930·2019-08-29 12:26
閱讀 3121·2019-08-28 17:52
閱讀 3537·2019-08-26 14:01
閱讀 3534·2019-08-26 12:19