免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
對<Effective Python: 編寫高質(zhì)量Python代碼的59個有效方法>中知識點的總結(jié)和擴(kuò)展

對<Effective Python: 編寫高質(zhì)量Python代碼的59個有效方法>中知識點的總結(jié)和擴(kuò)展

《Effective Python》一書結(jié)合Python的語言特性,對代碼規(guī)范進(jìn)行了詳細(xì)總結(jié),是一本非常不錯的Python實操指南。但我在閱讀的過程中發(fā)現(xiàn)有些地方僅僅是告知讀者“怎么做”,但是具體“為什么”不是很深入。下面內(nèi)容是我對這些知識點的總結(jié)和相應(yīng)原理的擴(kuò)展。

(如有不準(zhǔn)確之處歡迎指正)

  1. Python版本問題,略。


  1. 關(guān)于PEP8:這是Python代碼風(fēng)格的一些規(guī)范,感興趣的同學(xué)可以自行了解。


  1. 在Python3中,bytes和str是兩種截然不同的類型:

    bytes是計算機(jī)原始的二進(jìn)制格式,而str是包含Unicode字符的,開發(fā)者不能以+號之類的操作符直接對它們兩個進(jìn)行混合操作。

    實際上,它們互相之間是編碼(encode)與解碼(decode)的關(guān)系。

    >>> s = "哇哈">>> b = bytes(s,encoding="utf-8")  # encode>>> print(s)哇哈>>> print(b)b'\xe5\x93\x87\xe5\x93\x88'

    可以看到,s是str類型,返回的依舊是人類能懂的文字,而b則返回的實際上是6個16進(jìn)制,每一個代表一字節(jié)。

    注意,在bytes函數(shù)中使用了encoding參數(shù)并且賦值"utf-8"。為什么呢?這是因為s中保存的是unicode字符(也叫萬國碼),這種字符人類能看懂,但計算機(jī)是不懂的。如果要把它轉(zhuǎn)換成計算機(jī)能懂的語言(二進(jìn)制),就需要進(jìn)行編碼(encode),而utf-8是一種編碼的方式,通過這個方式可以將unicode編碼成bytes格式,反之就是解碼。

    一般而言Python在使用str的時候會自動編碼解碼,不需要我們操心。但如果開發(fā)者需要手動操作bytes類型的數(shù)據(jù)則需要顯式編碼。

    >>> s2 = str(b,encoding="utf-8")  # 這里參數(shù)是encoding但實際是decode了>>> print(s2)哇哈

    當(dāng)我們需要把bytes轉(zhuǎn)成str是一樣的,顯示注明編碼(解碼)方式,然后將bytes類型對象進(jìn)行解碼,得到原本的unicode字符。

  2. 不要寫巨復(fù)雜的單行表達(dá)式

    剛參加工作時寫了這么一句代碼:

    if (is_one_digit or is_two_digits or is_third_digits)                 and ((0< (current_digit-last_chinese_digit) <= 2)                        or ((last_chinese_digit == 9 or last_chinese_digit == 8) and current_digit == 0)                        or (last_chinese_digit == 0))                and is_selection_line_score<=0                 and calculation_or_not(rect_list)[0]>0.2:

    是不是很惡心?一般人看見這種代碼心里肯定萬馬狂奔。單行如果有多個and或or這種東西,最好是要拆開幾行來寫,然后再放到if語句中做判斷。

  3. 關(guān)于切片操作


    • 不要寫多余的代碼:能省略的就省略:
      >>> a = [1,2,3]>>> print(a[0:2])  # 0多余,可以省略。[1, 2]>>> print(a[:2])  # 如果從表頭開始,0可以省略:同理如果到表尾,表尾也可以省略。[1, 2]
    • 切片操作不計較索引是否越界,但訪問列表單個元素時索引不能越界:
      >>> a = [1,2,3]>>> b = a[:100]  # 切片無視越界>>> b[1, 2, 3]>>> c = a[100]  # 訪問單個元素索引越界報錯Traceback (most recent call last):File "<stdin>", line 1, in <module>IndexError: list index out of range
    • 左側(cè)list也可以使用切片操作:
      >>> a = [1,2,3,4,5,6]>>> a[:3] = [10,11]  # 右側(cè)值會將左側(cè)列表指定范圍內(nèi)的值替換掉。>>> a[10, 11, 4, 5, 6]
    • 切片操作是淺拷貝!
      深淺拷貝可參考我的另一篇博文:
      那些年在使用python過程中踩的一些坑。

  1. 在單次切片操作內(nèi),不要同時指定start,end與stride

    >>> a = [1,2,3,4,5,6,7,8,9,10]>>> print(a[1:5:2])  # 這樣寫顯得有些亂[2, 4]>>> b = a[1:5]  # 可以先做范圍切割>>> print(b[::2])  # 再做步進(jìn)切割[2, 4]

  1. 用列表推導(dǎo)式取代map和filter

    列表推導(dǎo)式異常好用,而且使得代碼看起來更簡潔:
    >>> a = [1,2,3,4,5,6,7,8,9,10]>>> b = [x+1 for x in a]  # 用一份列表制作另外一份>>> b[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]>>> c = [x+1 for x in a if x>5]  # 還可以添加條件判斷過濾掉一部分元素>>> c[7, 8, 9, 10, 11]

  1. 不要使用含有兩個以上表達(dá)式的列表推導(dǎo)

    列表推導(dǎo)支持多級循環(huán),也支持多個條件判斷,但最好不要寫太多,不然代碼很難懂。

    建議:
    2個條件,2個循環(huán),或者1個條件1個循環(huán).

  2. 使用生成器表達(dá)式來改寫數(shù)據(jù)量較大的列表推導(dǎo)

    生成器真的是Python中極為強(qiáng)大的一個功能,它與列表推導(dǎo)的不同在于:列表推導(dǎo)得到的是一個實實在在的列表,而生成器得到的是一個算法,通過這個算法可以一項一項計算得到我們想要的結(jié)果,這樣做就帶來了一個好處:節(jié)約內(nèi)存。

    >>> a = [1,2,3,4,5,6,7,8,9,10]>>> b = [x+1 for x in a]  # 列表推導(dǎo)式>>> c = (x+1 for x in a)  # 生成器表達(dá)式>>> b[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]>>> c<generator object <genexpr> at 0x000001F0CCE7D5C8>

    可以看到,通過列表推導(dǎo)得到的列表b保存的是一個完整的列表。如果這個列表有上千萬個元素,那么它占用的內(nèi)存空間無疑是巨大的。而c則只保存了一個生成器對象,它會在在你需要的時候一個一個計算出值。

    >>> for x in c:...    print(x)...234567891011

    生成器表達(dá)式還有另外一個好處:可以互相結(jié)合。

    >>> a = [1,2,3]>>> b = (x+1 for x in a)  # 通過b可以得到2,3,4>>> c = (y**2 for y in b)  # 通過c可以得到4,9,16>>> for y in c:...     print(y)...4916

    外圍的生成器每次前進(jìn)時,都會推動內(nèi)部的那個生成器,于是產(chǎn)生連鎖反應(yīng)。而且這種連鎖生成器表達(dá)式可以在Python中高效執(zhí)行。


    生成器是迭代器的一種。那么迭代器是什么呢?

    Python中有一種對象,它可以被for循環(huán)進(jìn)行遍歷,我們統(tǒng)稱這種對象為“可迭代對象”(Iteralbe)??傻鷮ο笾钥梢员谎h(huán)遍歷,是因為當(dāng)循環(huán)體作用到它身上時,會自動調(diào)用它內(nèi)部的__iter__方法使得它返回一個類似于“傳送帶”功能一樣的對象,這個對象會一個接一個把元素進(jìn)行返回。這個“傳送帶”即是迭代器(Iterator)。

    a = [1,2,3,4]for x in a:    print(x)# --------------------------# 下面這個語句塊與上面是等價的# --------------------------it = iter(a)  # 手動調(diào)用iter(),實際是調(diào)用a中__iter__方法,返回一個迭代器itwhile True:    try:        x = next(it)  # 使用next()函數(shù)不斷取迭代器中的下一個值。        print(x)    except StopIteration:  # 當(dāng)沒有值可取時會發(fā)生異常并結(jié)束循環(huán)。        break

    在Python中,list,dict,str等統(tǒng)統(tǒng)都是可迭代對象,也就是說,它們都可以執(zhí)行iter()函數(shù)。但它們并不是迭代器;迭代器是一種惰性計算序列,它只有當(dāng)你需要時才會計算相應(yīng)的值給你,生成器就是一種迭代器。

    總結(jié)一下:

    • 可迭代對象指的是可以作用于for循環(huán)的對象(或者說實現(xiàn)了__iter__方法的對象),iter()方法可以通過可迭代對象返回一個迭代器。
    • 迭代器指的是可以作用于next()函數(shù)的對象,它是一個惰性計算序列。
    • 生成器是一種迭代器。
  3. 使用enumerate取代range

    enumerate 可以直接得到當(dāng)前迭代器中每個元素的索引,寫起來更簡潔。

  4. 使用zip同時遍歷多個迭代器

    Python3 中的zip相當(dāng)于生成器,會在遍歷過程中逐次產(chǎn)生元組。需要注意的是,如果提供的迭代器長度不等,則zip會自動提前停止。

  5. 不要再for和while循環(huán)后面寫else塊

    從來沒這么寫過......略

  6. 合理運用try/except/else/final

    final語句塊用于執(zhí)行那些無論如何都要執(zhí)行的部分。
    else則用于將異常與非異常語句塊區(qū)分開,提升代碼可讀性。

(未完待續(xù))

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Python中的3個“黑魔法”與“騷操作”
Python基礎(chǔ)篇--迭代器,生成器和裝飾器
Python中生成器的原理及用法
Python迭代器和生成器詳解(包括yield詳解)
Python3高級特性(五)之容器(container)
Python中生成器和迭代器的區(qū)別
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服