0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

詳解Python里的分支代碼

python爬蟲知識(shí)分享 ? 來(lái)源:python爬蟲知識(shí)分享 ? 作者:python爬蟲知識(shí)分享 ? 2022-04-21 15:20 ? 次閱讀

Python 里的分支代碼

Python 支持最為常見的 if/else 條件分支語(yǔ)句,不過(guò)它缺少在其他編程語(yǔ)言中常見的 switch/case 語(yǔ)句。

除此之外,Python 還為 for/while 循環(huán)以及 try/except 語(yǔ)句提供了 else 分支,在一些特殊的場(chǎng)景下,它們可以大顯身手。

1. 避免多層分支嵌套

如果這篇文章只能刪減成一句話就結(jié)束,那么那句話一定是“要竭盡所能的避免分支嵌套”

過(guò)深的分支嵌套是很多編程新手最容易犯的錯(cuò)誤之一。假如有一位新手 JavaScript 程序員寫了很多層分支嵌套,那么你可能會(huì)看到一層又一層的大括號(hào):if { if { if { ... }}}。俗稱“嵌套 if 地獄(Nested If Statement Hell)”。

但是因?yàn)?Python 使用了縮進(jìn)來(lái)代替 {},所以過(guò)深的嵌套分支會(huì)產(chǎn)生比其他語(yǔ)言下更為嚴(yán)重的后果。比如過(guò)多的縮進(jìn)層次很容易就會(huì)讓代碼超過(guò) PEP8 中規(guī)定的每行字?jǐn)?shù)限制。讓我們看看這段代碼:

def buy_fruit(nerd, store):
    """去水果店買蘋果

    - 先得看看店是不是在營(yíng)業(yè)
    - 如果有蘋果的話,就買 1 個(gè)
    - 如果錢不夠,就回家取錢再來(lái)
    """
    if store.is_open():
        if store.has_stocks("apple"):
            if nerd.can_afford(store.price("apple", amount=1)):
                nerd.buy(store, "apple", amount=1)
                return
            else:
                nerd.go_home_and_get_money()
                return buy_fruit(nerd, store)
        else:
            raise MadAtNoFruit("no apple in store!")
    else:
        raise MadAtNoFruit("store is closed!")

上面這段代碼最大的問(wèn)題,就是過(guò)于直接翻譯了原始的條件分支要求,導(dǎo)致短短十幾行代碼包含了有三層嵌套分支。

這樣的代碼可讀性和維護(hù)性都很差。不過(guò)我們可以用一個(gè)很簡(jiǎn)單的技巧:“提前結(jié)束” 來(lái)優(yōu)化這段代碼:

def buy_fruit(nerd, store):
    if not store.is_open():
        raise MadAtNoFruit("store is closed!")

    if not store.has_stocks("apple"):
        raise MadAtNoFruit("no apple in store!")

    if nerd.can_afford(store.price("apple", amount=1)):
        nerd.buy(store, "apple", amount=1)
        return
    else:
        nerd.go_home_and_get_money()
        return buy_fruit(nerd, store)

“提前結(jié)束”指:在函數(shù)內(nèi)使用 returnraise 等語(yǔ)句提前在分支內(nèi)結(jié)束函數(shù)。比如,在新的 buy_fruit 函數(shù)里,當(dāng)分支條件不滿足時(shí),我們直接拋出異常,結(jié)束這段這代碼分支。這樣的代碼沒有嵌套分支,更直接也更易讀。

2. 封裝那些過(guò)于復(fù)雜的邏輯判斷

如果條件分支里的表達(dá)式過(guò)于復(fù)雜,出現(xiàn)了太多的 not/and/or,那么這段代碼的可讀性就會(huì)大打折扣,比如下面這段代碼:

# 如果活動(dòng)還在開放,并且活動(dòng)剩余名額大于 10,為所有性別為女性,或者級(jí)別大于 3
# 的活躍用戶發(fā)放 10000 個(gè)金幣
if activity.is_active and activity.remaining > 10 and \
        user.is_active and (user.sex == 'female' or user.level > 3):
    user.add_coins(10000)
    return

對(duì)于這樣的代碼,我們可以考慮將具體的分支邏輯封裝成函數(shù)或者方法,來(lái)達(dá)到簡(jiǎn)化代碼的目的:

if activity.allow_new_user() and user.match_activity_condition():
    user.add_coins(10000)
    return

事實(shí)上,將代碼改寫后,之前的注釋文字其實(shí)也可以去掉了。因?yàn)楹竺孢@段代碼已經(jīng)達(dá)到了自說(shuō)明的目的。至于具體的 什么樣的用戶滿足活動(dòng)條件? 這種問(wèn)題,就應(yīng)由具體的 match_activity_condition() 方法來(lái)回答了。

Hint: 恰當(dāng)?shù)姆庋b不光直接改善了代碼的可讀性,事實(shí)上,如果上面的活動(dòng)判斷邏輯在代碼中出現(xiàn)了不止一次的話,封裝更是必須的。不然重復(fù)代碼會(huì)極大的破壞這段邏輯的可維護(hù)性。

3. 留意不同分支下的重復(fù)代碼

重復(fù)代碼是代碼質(zhì)量的天敵,而條件分支語(yǔ)句又非常容易成為重復(fù)代碼的重災(zāi)區(qū)。所以,當(dāng)我們編寫條件分支語(yǔ)句時(shí),需要特別留意,不要生產(chǎn)不必要的重復(fù)代碼。

讓我們看下這個(gè)例子:

# 對(duì)于新用戶,創(chuàng)建新的用戶資料,否則更新舊資料
if user.no_profile_exists:
    create_user_profile(
        username=user.username,
        email=user.email,
        age=user.age,
        address=user.address,
        # 對(duì)于新建用戶,將用戶的積分置為 0
        points=0,
        created=now(),
    )
else:
    update_user_profile(
        username=user.username,
        email=user.email,
        age=user.age,
        address=user.address,
        updated=now(),
    )

在上面的代碼中,我們可以一眼看出,在不同的分支下,程序調(diào)用了不同的函數(shù),做了不一樣的事情。但是,因?yàn)槟切┲貜?fù)代碼的存在,我們卻很難簡(jiǎn)單的區(qū)分出,二者的不同點(diǎn)到底在哪。

其實(shí),得益于 Python 的動(dòng)態(tài)特性,我們可以簡(jiǎn)單的改寫一下上面的代碼,讓可讀性可以得到顯著的提升:

if user.no_profile_exists:
    profile_func = create_user_profile
    extra_args = {'points': 0, 'created': now()}
else:
    profile_func = update_user_profile
    extra_args = {'updated': now()}

profile_func(
    username=user.username,
    email=user.email,
    age=user.age,
    address=user.address,
    **extra_args
)

當(dāng)你編寫分支代碼時(shí),請(qǐng)額外關(guān)注由分支產(chǎn)生的重復(fù)代碼塊,如果可以簡(jiǎn)單的消滅它們,那就不要遲疑。

4. 謹(jǐn)慎使用三元表達(dá)式

三元表達(dá)式是 Python 2.5 版本后才支持的語(yǔ)法。在那之前,Python 社區(qū)一度認(rèn)為三元表達(dá)式?jīng)]有必要,我們需要使用 x and a or b 的方式來(lái)模擬它。[注]

事實(shí)是,在很多情況下,使用普通的 if/else 語(yǔ)句的代碼可讀性確實(shí)更好。盲目追求三元表達(dá)式很容易誘惑你寫出復(fù)雜、可讀性差的代碼。

所以,請(qǐng)記得只用三元表達(dá)式處理簡(jiǎn)單的邏輯分支。

language = "python" if you.favor("dynamic") else "golang"

對(duì)于絕大多數(shù)情況,還是使用普通的 if/else 語(yǔ)句吧。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4788

    瀏覽量

    68625
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4797

    瀏覽量

    84694
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    十幾種格力空調(diào)故障代碼詳解

    十幾種格力空調(diào)故障代碼詳解,查表一目了然
    發(fā)表于 11-27 15:15 ?0次下載

    使用Python進(jìn)行串口通信的案例

    python復(fù)制代碼 import serialimport time # 配置串口參數(shù)serial_port = '/dev/ttyUSB0' # 在Windows上可能是 'COM3' 或其他類
    的頭像 發(fā)表于 11-22 09:11 ?201次閱讀

    對(duì)比Python與Java編程語(yǔ)言

    Python與Java都是目前非常流行的編程語(yǔ)言,它們各有其獨(dú)特的優(yōu)勢(shì)和適用場(chǎng)景。以下是對(duì)這兩種編程語(yǔ)言的對(duì)比: 一、語(yǔ)法和易用性 Python 語(yǔ)法簡(jiǎn)潔,代碼更易讀,非常適合初學(xué)者。 動(dòng)態(tài)類型系統(tǒng)
    的頭像 發(fā)表于 11-15 09:31 ?320次閱讀

    Python代理技術(shù)詳解:從入門到進(jìn)階

    Python代理技術(shù)是一種在網(wǎng)絡(luò)編程中廣泛使用的技術(shù),它允許通過(guò)代理服務(wù)器發(fā)送和接收網(wǎng)絡(luò)請(qǐng)求。
    的頭像 發(fā)表于 11-12 07:06 ?253次閱讀

    使用Python進(jìn)行圖像處理

    下面是一個(gè)關(guān)于使用Python在幾行代碼中分析城市輪廓線的快速教程。
    的頭像 發(fā)表于 11-07 10:14 ?224次閱讀
    使用<b class='flag-5'>Python</b>進(jìn)行圖像處理

    Python常用函數(shù)大全

    Python 世界,有一些寶藏函數(shù)和模塊,它們可以讓你編程更輕松、代碼更高效。這篇文章將帶你一一認(rèn)識(shí)這些神器,讓你的開發(fā)生活瞬間輕松不少!
    的頭像 發(fā)表于 10-27 17:20 ?253次閱讀

    PDF文件批量打印源代碼

    壓縮包中包含可批量打印PDF文件的Python代碼,可以借助PYcharm工具執(zhí)行,實(shí)現(xiàn)多PDF文件同時(shí)打印。
    發(fā)表于 08-08 14:26 ?0次下載

    pytorch和python的關(guān)系是什么

    ,PyTorch已經(jīng)成為了一個(gè)非常受歡迎的框架。本文將介紹PyTorch和Python之間的關(guān)系,以及它們?cè)谏疃葘W(xué)習(xí)領(lǐng)域的應(yīng)用。 Python簡(jiǎn)介 Python是一種高級(jí)、解釋型、通用的編程語(yǔ)言,由Guido van Rossu
    的頭像 發(fā)表于 08-01 15:27 ?1970次閱讀

    用pycharm進(jìn)行python爬蟲的步驟

    提供了許多有用的功能,如代碼自動(dòng)完成、調(diào)試和版本控制等。您可以從JetBrains的官方網(wǎng)站下載PyCharm,并根據(jù)您的需求選擇免費(fèi)社區(qū)版或付費(fèi)專業(yè)版。 創(chuàng)建一個(gè)新的Python項(xiàng)目 打開
    的頭像 發(fā)表于 07-11 10:11 ?851次閱讀

    深度學(xué)習(xí)常用的Python庫(kù)

    深度學(xué)習(xí)作為人工智能的一個(gè)重要分支,通過(guò)模擬人類大腦中的神經(jīng)網(wǎng)絡(luò)來(lái)解決復(fù)雜問(wèn)題。Python作為一種流行的編程語(yǔ)言,憑借其簡(jiǎn)潔的語(yǔ)法和豐富的庫(kù)支持,成為了深度學(xué)習(xí)研究和應(yīng)用的首選工具。本文將深入探討
    的頭像 發(fā)表于 07-03 16:04 ?653次閱讀

    ESP32下如何加自定義Python庫(kù)?

    我看官方有提供Micropython的bin文件,但我想根據(jù)自己外設(shè)擴(kuò)充一下Python庫(kù),這個(gè)應(yīng)該從哪里入手? 之前做過(guò)RTT系統(tǒng)的python庫(kù)擴(kuò)充,RTT有提供Micropython的源代碼,直接在里面加自己的庫(kù)就行 ES
    發(fā)表于 06-18 06:27

    谷歌升級(jí)Bard AI聊天機(jī)器人為Gemini,新增Python代碼編輯功能

     此外,谷歌表示,接下來(lái)數(shù)個(gè)月內(nèi),Gemini Advanced 計(jì)劃會(huì)加入更多新功能,如支持更為詳盡的上下文信息、增強(qiáng)多模態(tài)交互性以及完善編程功能。據(jù)谷歌公開更新,付費(fèi)用戶可用 Gemini 界面直接編輯和執(zhí)行 Python 代碼,有助于快速驗(yàn)證試驗(yàn)
    的頭像 發(fā)表于 02-20 15:47 ?591次閱讀

    python中open函數(shù)的用法詳解

    python中open函數(shù)的用法詳解 Python中的open()函數(shù)用于打開文件。它接受文件名和模式作為參數(shù),并返回一個(gè)文件對(duì)象。文件對(duì)象可用于讀取、寫入和管理文件。 open()函數(shù)的基本語(yǔ)法
    的頭像 發(fā)表于 01-30 15:31 ?2129次閱讀

    制造企業(yè)分支機(jī)構(gòu)如何高效互聯(lián)?

    ? 隨著制造企業(yè)業(yè)務(wù)的不斷擴(kuò)張,分布在不同地區(qū)的分支機(jī)構(gòu)逐漸成為提高市場(chǎng)覆蓋和降低生產(chǎn)成本的重要手段。然而,分支機(jī)構(gòu)的增多也帶來(lái)了管理和協(xié)調(diào)的挑戰(zhàn)。為了有效管理和協(xié)調(diào)各個(gè)分支機(jī)構(gòu)的運(yùn)營(yíng),建立一個(gè)高效
    的頭像 發(fā)表于 01-25 16:26 ?450次閱讀

    Python智能家居系統(tǒng)代碼介紹

    Python智能家居系統(tǒng)是一種基于Python編程語(yǔ)言開發(fā)的智能家居控制系統(tǒng),在現(xiàn)代家庭中得到了越來(lái)越廣泛的應(yīng)用。本文將詳細(xì)介紹Python智能家居系統(tǒng)的代碼實(shí)現(xiàn),包括系統(tǒng)的結(jié)構(gòu)與功能
    的頭像 發(fā)表于 01-25 09:46 ?1367次閱讀