1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        【Python】Python小技巧:?args 和 kwargs 的樂(lè)趣

        共 3018字,需瀏覽 7分鐘

         ·

        2022-05-27 21:24


        這篇文章是偉兄給我的稿子,總結(jié)實(shí)用、到位。另外,歡迎訪問(wèn)并關(guān)注他的博客:
        https://jl-zhenlaixiaowei.blog.csdn.net/
        我曾經(jīng)和一個(gè)聰明的 Pythonista 結(jié)對(duì)編程,每次他輸入帶有可選或關(guān)鍵字參數(shù)的函數(shù)定義時(shí),他都會(huì)驚呼“argh!”和“kwargh!”。
        要不然我們相處的很好,我猜想這就是學(xué)術(shù)界編程最終對(duì)人所帶來(lái)的影響吧。
        現(xiàn)在argskwargs參數(shù)仍然是 Python 中非常有用的特性,而且理解它們的威力將使您成為更有效的開(kāi)發(fā)人員。

        那么“args”和“kwargs”參數(shù)用來(lái)做什么呢?

        它們?cè)试S一個(gè)函數(shù)接受可選參數(shù),因此你能夠在你的模塊和類(lèi)里創(chuàng)建彈性APIs。
        示例代碼如下:
        In?[2]:?def?foo(required,?*args,?**kwargs):
        ???...:?????print(required)
        ???...:?????if?args:
        ???...:?????????print(args)
        ???...:?????if?kwargs:
        ???...:?????????print(kwargs)
        上面的函數(shù)需要至少一個(gè)叫做“必須的”參數(shù),但是它也能接受額外的位置參數(shù)和關(guān)鍵字參數(shù)。
        如果我們調(diào)用帶有附加參數(shù)的函數(shù),參數(shù)將會(huì)收集額外的位置參數(shù)作為一個(gè)元組,因?yàn)檫@個(gè)參數(shù)的名字有一個(gè)*(單星號(hào))前綴。
        同樣地,kwargs將收集額外的關(guān)鍵字參數(shù)作為一個(gè)字典,因?yàn)檫@個(gè)參數(shù)名字有**(雙星號(hào))前綴。
        如果沒(méi)有附加參數(shù)被傳遞給函數(shù)。args 和 kwargs 可以為空。
        當(dāng)我們調(diào)用帶有參數(shù)的不同組合的函數(shù)時(shí),你會(huì)看到在args和kwargs內(nèi)部參數(shù)。
        Python如何收集它們,根據(jù)它們是否為位置參數(shù)或者關(guān)鍵字參數(shù)。代碼如下:
        In?[3]:?foo()
        ---------------------------------------------------------------------------
        TypeError?????????????????????????????????Traceback?(most?recent?call?last)
        -3
        -c19b6d9633cf>?in?
        ---->?1?foo()

        TypeError:?foo()?missing?1?required?positional?argument:?'required'
        In?[4]:?foo('hello')
        hello
        In?[5]:?foo('hello',?1,?2,?3)
        hello
        (1,?2,?3)

        In?[6]:?foo('hello',?1,?2,?3,?key1='value',?key2=999)
        hello
        (1,?2,?3)
        {'key1':?'value',?'key2':?999}
        我要明確一下,調(diào)用args和kwargs參數(shù)是簡(jiǎn)單的命名慣例。
        像之前的例子里,如果稱(chēng)他們*parms和**argv也可以。實(shí)際上語(yǔ)法分別是單星號(hào)(*)或者雙星號(hào)(**)。
        然而,我還是推薦你還是堅(jiān)持可接受的命名慣例以避免混淆。(而且每隔一段時(shí)間還有機(jī)會(huì)喊“argh!”和“kwargh!”)。

        ## 轉(zhuǎn)發(fā)可選或者關(guān)鍵字參數(shù)

        有可能從一個(gè)函數(shù)到另一個(gè)函數(shù)傳遞可選或者關(guān)鍵字參數(shù)。
        當(dāng)你調(diào)用要轉(zhuǎn)發(fā)參數(shù)的函數(shù)時(shí),你可以通過(guò)使用解包參數(shù)操作符*和**。在你傳遞之前這也給你一個(gè)機(jī)會(huì)修改參數(shù)。
        示例如下:
        In?[8]:?def?foo(x,?*args,?**kwargs):
        ???...:?????kwarg['name']?=?'Alice'
        ???...:?????new_args?=?args?+?('extra',?)
        ???...:?????bar(x,?*new_args,?**kwargs)
        這種技術(shù)對(duì)于子類(lèi)化和編寫(xiě)包裝函數(shù)很有用。
        例如,您可以使用它來(lái)擴(kuò)展父類(lèi)的行為,而不必在子類(lèi)中復(fù)制其構(gòu)造函數(shù)的完整簽名。
        如果您使用的 API 可能會(huì)在您的控制之外發(fā)生變化,這會(huì)非常方便,示例代碼如下:
        In?[9]:?class?Car:
        ???...:?????def?__init__(self,?color,?mileage):
        ???...:?????????self.color?=?color
        ???...:?????????self.mileage?=?mileage
        ???...:?

        In?[10]:?class?AlwaysBlueCar(Car):
        ????...:?????def?__init__(self,?*args,?**kwargs):
        ????...:?????????super().__init__(*args,?**kwargs)
        ????...:?????????self.color?=?'blue'

        In?[12]:?AlwaysBlueCar('green',?48392).color
        Out[12]:?'blue'
        AlwaysBlueCar 構(gòu)造函數(shù)只是將所有參數(shù)傳遞給它的父類(lèi),然后覆蓋一個(gè)內(nèi)部屬性。
        這意味著如果父類(lèi)構(gòu)造函數(shù)發(fā)生更改,AlwaysBlueCar 很有可能仍會(huì)按預(yù)期運(yùn)行。
        這里的缺點(diǎn)是 AlwaysBlueCar 構(gòu)造函數(shù)現(xiàn)在有一個(gè)相當(dāng)無(wú)用的簽名——如果不查找父類(lèi),我們不知道它需要什么參數(shù)。
        通常,您不會(huì)將這種技術(shù)用于您自己的類(lèi)層次結(jié)構(gòu)。更有可能的情況是您想要修改或覆蓋某些您無(wú)法控制的外部類(lèi)中的行為。
        但這總是危險(xiǎn)的領(lǐng)域,所以最好小心(否則你可能很快就會(huì)有另一個(gè)理由尖叫“argh!”)。
        這種技術(shù)可能有用的另一種情況是編寫(xiě)包裝函數(shù),例如裝飾器。在那里,您通常還希望接受要傳遞給包裝函數(shù)的任意參數(shù)。
        而且,如果我們可以在不必復(fù)制和粘貼原始函數(shù)簽名的情況下做到這一點(diǎn),那可能更易于維護(hù):
        import?functools
        def?trace(f):
        ????...:[email protected](f)
        ????...:?????def?decorated_function(*args,?**kwargs):
        ????...:?????????print(f,?args,?kwargs)
        ????...:?????????result?=?f(*args,?**kwargs)
        ????...:?????????print(result)
        ????...:?????return?decorated_function
        ????
        In?[11]:?@trace
        ????...:?def?greet(greeting,?name):
        ????...:?????return?'{},?{}!'.format(greeting,?name)
        In?[14]:?greet('Hello',?'Bob')
        0x7fefa69db700
        >?('Hello',?'Bob')?{}
        Hello,?Bob!
        使用像這樣的技術(shù),有時(shí)很難在使代碼足夠明確的想法和遵守不要重復(fù)自己(DRY)原則的想法之間取得平衡。
        這可能永遠(yuǎn)是一個(gè)艱難的選擇。如果你能從同事那里得到第二個(gè)意見(jiàn),我鼓勵(lì)你嘗試一下。
        往期精彩回顧




        瀏覽 28
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            牛牛影视av | 91美女在线 | 国产在线麻豆精品入口 | 97在线人人| 日韩人妻无码一区二区三区 | 亚洲AV无码乱码国产精品蜜芽 | 色逼高清 | 黄色欧美网站在线观看 | 亚洲另类图片小说 | 国产人妻无码一区二区三区不卡 |