【Python自學】09.函數基礎(中)

函數的參數

轉瞬一年,又快到動物們交...(*/?\*),嘛~拖更無限好...
                           

我錯了我錯了

咳咳,去年說的函數的定義時有包含參數,只要把參數的名字和位置確定下來,函數的 接口 定義就完成了。函數調用者只需知道如何傳遞正確的參數,以及函數將返回什么樣的值就夠了,內部的復雜邏輯被封裝,無需了解。


位置參數

def power(x):
  return x * x

對于上述的 power(x) 函數,參數 x 就是一個位置參數。位置參數可以有多個。例如將上述程序做如下修改,調用的時候,傳入兩個值按照位置順序依次賦予 x 和 n :

def power(x, n):
  s = 1
  while n > 0:
    n = n - 1
    s = s * x
  return s


默認參數

重新定義的 power(x,n) 可以用在計算任意 n 次方,但是舊的代碼調用失效了,如果只是輸入一個參數,會使得舊代碼因缺少一個參數而無法正常調用:
  >>> power(5)
  Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  TypeError: power() missing 1 required positional argument: 'n'

如果想要舊代碼那種,輸入一個參數,自動獲得平方結果。就可以使用默認參數了:
  def power(x,n=2):
     s= 1
    while n > 0:
       n = n-1
      s = s * x
  return s
之后,運行:    
  >>>power(5)
  >>>25

設置默認參數需要注意幾點:
     一、必選參數在前,默認參數在后,否則 Python 解釋器會報錯;
     二、函數變化大的參數放前面,小的就可以作為默認參數放在后頭;

設置默認參數可以降低函數的難度,復雜點的函數也可以放多幾個參數,也方便用戶使用。eg:
   def enroll(name,gender,age=6,city='beijing'):
    print('name:',name)
    print('gender:',gender)
    print('age:',age)
    print('city:',city)
運行:
  >>> enroll('Lily','F')
  name: Lily
  gender: F
  age: 6
  city: beijing

不按照順序給參數:

>>> enroll('Lala','C','city=shanwei')

但是默認參數使用不當,也會出現不少bug,例如:
  def add_end(L=[]):
    L.append('END')
    return L

此程序在正常調用時是傳入一個 list,在其末尾處放入個 END,再返回,例如[1,2,3],返回[1,2,3,'END']。但是如果使用默認參數調用時,第一次正常,但是多調用幾次就可以發現...

原因很簡單,默認參數指向了可變對象,所以 L 好像記住了 'END'。所以定義默認參數還需要注意,默認參數必須指向不可變對象(str/None等)!
   修改法:
  def add_end(L=None):
    if L is None:
      L=[]
      L.append('END')
    return L


可變參數

可變參數,參數的數量可以任意個。以數學題為例,給定一組數字a,b,c...,要求計算出它們的平方和。方法之一可以將這組數字作為 list 或者 tuple 參數傳入:
    def calc(numbers):
       sum = 0
      for n in numbers:
        sum=sum+nn
      return sum
  但是每次得先把這組數據組成 list 或者 tuple,例如calc([1,2,3])是略微麻煩的。可以稍微改動一下:
   def calc(
numbers):
    sum = 0
    for n in numbers:
      sum=sum+n*n
    return sum
  代碼基本不變,但是加了個 ,就可以直接傳入所需要的數據參數了,calc(1,2,3)。
  而如果已經有了一個 list 或 tuple 數據參數,例如nums=[1,2,3],導入可不需要 calc(nums[0],nums[1],nums[2]),只需要在調用時輸入 calc(*nums) 即可。
  
nums 表示把 nums 這個 list 的所有元素作為可變參數傳進去。


關鍵字參數

可變參數允許傳入任意個參數,這些參數在函數調用時自動組裝成一個 tuple 。而關鍵字參數是允許傳入任意個參數,然后在調用函數的時候自動組裝成一個 dict。
  eg:
  def person(name,age,**kw):
    print('name:',name,'age:',age,'other:',kw) 
  調用:
    >>> person('小明',20)
    name: 小明 age: 20 other: {}
    >>> person('小紅','18',性別='男',QQ簽名='小明滾犢子,我們不會在一起的')
    name: 小紅 age: 18 other: {'性別': '男', 'QQ簽名': '小明滾犢子,我們不會在一起的'}

關鍵字參數可以用在例如用戶注冊的場景,需要輸入的位置參數是必填選項,關鍵字參數是可選,例如備注等。
  當然跟可變參數一樣,可以先組裝個 dict ,然后再導入:  
    >>> extra = {'city': 'Beijing', 'job': 'Engineer'}
    >>> person('Jack', 24, city=extra['city'], job=extra['job'])
  也可以用可變參數類似的方法 **extra,把extra這個dict的所有key-value用關鍵字參數傳入到函數的**kw參數,kw將獲得一個dict,注意kw獲得的dict是extra的一份拷貝,對kw的改動不會影響到函數外的extra。


命名關鍵字

函數的調用者可以傳入任意不受限制的關鍵字參數,但至于傳入了哪些就需要在函數內部通過 kw 檢查。
    def person(name, age, **kw):
       if 'city' in kw:
         # 有city參數
        pass
      if 'job' in kw:
         # 有job參數
        pass
      print('name:', name, 'age:', age, 'other:', kw)

但是如果要限制關鍵字參數的名字,就可以命名關鍵字。例如只接收 city 和 job 作為關鍵字參數,可以由缺省值,簡化調用:
    def person(name,age,*,job='teacher',city):
      print(name,age,job,city)

如果定義中已經有一個可變參數,后面跟著的命名關鍵字就不再需要一個特殊分隔符 * ,但是沒有可變參數的時候必須有分隔符 * :
    def person(name,age,*args,job,city):
      print(name,age,args,job,city)

調用的時候,必須傳入參數名:
    >>> person('小明',20,job='工程師',city='北京','簽名:小紅我愛你啊')
    SyntaxError: positional argument follows keyword argument

>>> person('小明',20,job='工程師',city='北京')
    小明 20 工程師 北京
 
    >>> person('小明',20,'工程師','北京')
    Traceback (most recent call last):
    File "<pyshell#70>", line 1, in <module>
    person('小明',20,'工程師','北京')
    TypeError: person() takes 2 positional arguments but 4 were given


參數組合

在定義函數的時候,可以用必選參數、默認參數、可變參數、關鍵字參數和命名參數或者它們的組合。但是參數定義的順序必須是:必選參數、默認參數、可變參數、命名關鍵字參數和關鍵字參數。
    def f1(a, b, c=0, *args, **kw):
      print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
      print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw) 
    在調用的時候:
      >>> f1(1, 2)
      a = 1 b = 2 c = 0 args = () kw = {}
      >>> f1(1, 2, c=3)
      a = 1 b = 2 c = 3 args = () kw = {}
      >>> f1(1, 2, 3, 'a', 'b')
      a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
      >>> f1(1, 2, 3, 'a', 'b', x=99)
      a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
      >>> f2(1, 2, d=99, ext=None)
      a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

還可以使用 tuple 和 dict 調用。任意函數,都可以通過類似 func(args,*kw)的形式調用它,無論參數是怎么定義的:

>>> args = (1, 2, 3, 4)
      >>> kw = {'d': 99, 'x': '#'}
      >>> f1(*args, *kw)
      a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}
        
      >>> args = (1, 2, 3)
      >>> kw = {'d': 88, 'x': '#'}
      >>> f2(
args, **kw)
      a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容

  • Python 是一種相當高級的語言,通過 Python 解釋器把符合語法的程序代碼轉換成 CPU 能夠執行的機器碼...
    Python程序媛閱讀 1,928評論 0 3
  • 基礎1.r''表示''內部的字符串默認不轉義2.'''...'''表示多行內容3. 布爾值:True、False(...
    neo已經被使用閱讀 1,706評論 0 5
  • 1.定義函數: 沒有return,默認返回None 2.定義空函數 相當于什么也不做,可以用來做函數體占位符,沒有...
    maskwang520閱讀 325評論 0 0
  • 函數名其實就是指向一個函數對象的引用,完全可以把函數名賦給一個變量,相當于給這個函數起了一個“別名”:a = ab...
    bjchenli閱讀 627評論 0 0
  • import math a = absprint(a(-1))n1 = 255print(str(hex(n1))...
    Elder閱讀 1,470評論 0 1