Python學習(二)

函數

定義格式

"""
def 函數名 ():
    # some codes
    ...
    
"""

# 求一個數的絕對值
def my_abs(x):
    if x > 0:
        return x
    else:
        return -x

空函數

# 定義一個什么事都不做的函數,pass僅是一個占位符,保證編譯通過
def fn():
pass

返回值

上面的示例中求絕對值的函數是返回的一個值,在Python中還可以返回多個值,但其實最終返回結果就是一個tuple。下面是一個求一元二次方程的函數

# 導入第三方模塊的API,相當于Java中的導包
import math


def test(a, b, c):
    # b ** 2 表示b的平方    b ** 3 表示b的立方,依此在推
    delta = b ** 2 - 4 * a * c
    if delta > 0:
        ret1 = (-b + math.sqrt(delta)) / (2 * a)
        ret2 = (-b - math.sqrt(delta)) / (2 * a)
        return ret1, ret2
    else:
        return "無解"


print(test(2, 3, 1))    # (-0.5, -1.0)

判斷參數類型

在上面的my_abs函數中,我們是對一個整數求絕對值,但若調用者傳遞過來的不是個整數怎么辦?所以我們需要對參數進行判斷。我們可以使用isinstance()函數來判斷

def my_abs(x):
# isinstance譯為是實例,加了一個not就表示不是實例(相當于java中的"!"符號)
if not isinstance(x, (int, float)):
    # 當參數不合法時我們可以在方法拋出類型錯誤(相當于Java中的異常)
    raise TypeError("arguments is not correct")
if x >= 0:
    return x
else:
    return -x

函數參數類型分類

  • 位置參數

      # 計算一個數的平方
      def test(x):
          return x ** 2
    

    x在test函數中就是一個位置參數,被調用時是必須要傳的。假如要計算一個數的立方,那么這個函數就不符合需求了,不過我們可以將計算幾次方讓用戶傳進來。

      def test(x, n):
          return x ** n
    
  • 默認參數

    不過,我們經常計算一個數的平方,所以我們可以設置一個默認參數,若調用者沒有傳第二個參數,那就使用默認參數,若傳了,就使用調用者的傳過來的參數

      def test(x, n=2):
          return x ** n
    

    默認參數使用注意

      def add_end(list=[]):
      list.append("end")
      return list
    
      # 第一次
      print(add_end())        # ['end']
      # 第二次
      print(add_end())        # ['end', 'end']
    

    這里有一個問題:默認參數是[],但是函數似乎每次都“記住了”上次添加了'end'后的list?

    第一次調用后,list的值由[]變為了 'end',由于參數list是一個變量,如果改變了list的內容,則下次調用時,默認參數的內容就變了,不再是函數定義時的[]了。

    所以,定義默認參數時必須指向不變對象

    上面的代碼可以這樣寫

      def add_end(list=None):
      if list is None:
          list = []
      list.append("end")
      return list
    
      # 第一次
      print(add_end())            # ['end']
      # 第二次
      print(add_end())            # ['end']
    

    對于str、None這樣的不可變對象,當它們被創建時,對象的內部數據是不能被修改的。這樣做的好處就是減少了因修改數據導致的錯誤,并且,在多任務的環境下同時讀取對象不需要加鎖。所以,如果可以設計一個不變對象,那就盡量設計成不變對象。

  • 可變參數

    可變參數就是指參數的個數是可以變的。

      # 比如給定一組數字a,b,c……,請計算a2 + b2 + c2 + ……。
      def calc(*num):
          ret = 0
          print(num)              # (1, 2, 3, 4)
          for n in num:
              ret += n * n
          return ret
      
      print(calc(1, 2, 3, 4))     # 30
      nums = [3, 4, 5, 6]
      # 假若傳的參數是list或tuple,我們可以這樣傳
      print(calc(*nums))
    

    當calc被調用時,雖然傳過來的是1,2,3,4,但是函數內部會先把它轉換成一個tuple,然后執行for循環

  • 關鍵字參數

    關鍵字參數用來對函數進行擴展

      # 比如在注冊時,除了名字是必填外,年齡、性別是可選項
      def register(name, **kw):
          print("name:", name, "other:", kw)
      
      register("Blain", sex="male", age=18)       # name: Blain other: {'sex': 'male', 'age': 18}
      info = {"city": "HuNan", "job": "Engineer"}
      # 假若傳的參數是dict,我們可以這樣傳
      register("Blain", **info)                   # name: Blain other: {'job': 'Engineer', 'city': 'HuNan'}
    

    與可變參數類似,會先把傳過來的參數轉換成一個dict,然后執行下面的代碼

  • 命名關鍵字參數

    命名關鍵字參數用來限制關鍵字參數的名字

      def register(name, *, city_name, job_name):
          print(name, city_name, job_name)
      
      register("Blain", city_name="SZ", job_name="Engineer")
      register("Blain", city="GZ", job_name="Salesman")
    

    打印結果如下:

      Traceback (most recent call last):
      Blain SZ Engineer
        File "...", line 91, in <module>
          register("Blain", city="GZ", job_name="Salesman")
      TypeError: register() got an unexpected keyword argument 'city'
    

    很顯然,第二次調用時我們傳的是city,與命名參數不符,報一個TypeError的錯誤

    如果函數的參數有一個可變參數時,后面的命名參數就不需要*

      def register(name, age, *args, city, job):
          print(name, age, args, city, job)
    
  • 參數組合

    在Python函數中,參數的定義順序為:位置參數,默認參數,可變參數,命名關鍵字參數,關鍵字參數

      def func1(a, b, c=0, *args, **kw):
          print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
      
      def func2(a, b, c=0, *, d, **kw):
          print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
      
      func1(1, 2)                     # a = 1 b = 2 c = 0 args = () kw = {}
      func1(1, 2, c=3)                # a = 1 b = 2 c = 3 args = () kw = {}
      func1(1, 2, 3, "a", "b")        # a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
      func1(1, 2, 3, "a", "b", x=10)  # a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 10}
      func2(1, 2, d=15, y=15)         # a = 1 b = 2 c = 0 d = 15 kw = {'y': 15}
    

總結

  • *args是可變參數,args接收的是一個tuple;

  • **kw是關鍵字參數,kw接收的是一個dict;

  • 可變參數既可以直接傳入:func(1, 2, 3),又可以先組裝list或tuple,再通過*args傳入:func(*(1, 2, 3))

  • 關鍵字參數既可以直接傳入:func(a=1, b=2),又可以先組裝dict,再通過**kw傳入:func(**{'a': 1, 'b': 2})

  • 使用*args**kw是Python的習慣寫法,當然也可以用其他參數名,但最好使用習慣用法。

  • 命名的關鍵字參數是為了限制調用者可以傳入的參數名,同時可以提供默認值。

  • 定義命名的關鍵字參數在沒有可變參數的情況下不要忘了寫分隔符*,否則定義的將是位置參數。

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

推薦閱讀更多精彩內容