<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【Python】Python小技巧:?args 和 kwargs 的樂趣

          共 3018字,需瀏覽 7分鐘

           ·

          2022-05-27 21:24


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

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

          它們允許一個函數(shù)接受可選參數(shù),因此你能夠在你的模塊和類里創(chuàng)建彈性APIs。
          示例代碼如下:
          In?[2]:?def?foo(required,?*args,?**kwargs):
          ???...:?????print(required)
          ???...:?????if?args:
          ???...:?????????print(args)
          ???...:?????if?kwargs:
          ???...:?????????print(kwargs)
          上面的函數(shù)需要至少一個叫做“必須的”參數(shù),但是它也能接受額外的位置參數(shù)和關(guān)鍵字參數(shù)。
          如果我們調(diào)用帶有附加參數(shù)的函數(shù),參數(shù)將會收集額外的位置參數(shù)作為一個元組,因為這個參數(shù)的名字有一個*(單星號)前綴。
          同樣地,kwargs將收集額外的關(guān)鍵字參數(shù)作為一個字典,因為這個參數(shù)名字有**(雙星號)前綴。
          如果沒有附加參數(shù)被傳遞給函數(shù)。args 和 kwargs 可以為空。
          當我們調(diào)用帶有參數(shù)的不同組合的函數(shù)時,你會看到在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ù)是簡單的命名慣例。
          像之前的例子里,如果稱他們*parms和**argv也可以。實際上語法分別是單星號(*)或者雙星號(**)。
          然而,我還是推薦你還是堅持可接受的命名慣例以避免混淆。(而且每隔一段時間還有機會喊“argh!”和“kwargh!”)。

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

          有可能從一個函數(shù)到另一個函數(shù)傳遞可選或者關(guān)鍵字參數(shù)。
          當你調(diào)用要轉(zhuǎn)發(fā)參數(shù)的函數(shù)時,你可以通過使用解包參數(shù)操作符*和**。在你傳遞之前這也給你一個機會修改參數(shù)。
          示例如下:
          In?[8]:?def?foo(x,?*args,?**kwargs):
          ???...:?????kwarg['name']?=?'Alice'
          ???...:?????new_args?=?args?+?('extra',?)
          ???...:?????bar(x,?*new_args,?**kwargs)
          這種技術(shù)對于子類化和編寫包裝函數(shù)很有用。
          例如,您可以使用它來擴展父類的行為,而不必在子類中復(fù)制其構(gòu)造函數(shù)的完整簽名。
          如果您使用的 API 可能會在您的控制之外發(fā)生變化,這會非常方便,示例代碼如下:
          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ù)傳遞給它的父類,然后覆蓋一個內(nèi)部屬性。
          這意味著如果父類構(gòu)造函數(shù)發(fā)生更改,AlwaysBlueCar 很有可能仍會按預(yù)期運行。
          這里的缺點是 AlwaysBlueCar 構(gòu)造函數(shù)現(xiàn)在有一個相當無用的簽名——如果不查找父類,我們不知道它需要什么參數(shù)。
          通常,您不會將這種技術(shù)用于您自己的類層次結(jié)構(gòu)。更有可能的情況是您想要修改或覆蓋某些您無法控制的外部類中的行為。
          但這總是危險的領(lǐng)域,所以最好小心(否則你可能很快就會有另一個理由尖叫“argh!”)。
          這種技術(shù)可能有用的另一種情況是編寫包裝函數(shù),例如裝飾器。在那里,您通常還希望接受要傳遞給包裝函數(shù)的任意參數(shù)。
          而且,如果我們可以在不必復(fù)制和粘貼原始函數(shù)簽名的情況下做到這一點,那可能更易于維護:
          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ù),有時很難在使代碼足夠明確的想法和遵守不要重復(fù)自己(DRY)原則的想法之間取得平衡。
          這可能永遠是一個艱難的選擇。如果你能從同事那里得到第二個意見,我鼓勵你嘗試一下。
          往期精彩回顧




          瀏覽 28
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  一本道亚洲 | 国产香蕉精品视频 | 黄色片大全 | 超碰中文字幕在线 | 国产精品秘 久久久久久 |