Python函數中參數類型


在學習Python函數的時候,函數本身的定義和調用並不是很復雜,但是函數的參數類型和用法的確有些復雜。在此做一個小結,加深理解。

Python參數的定義

  • 負責給函數提供一些必要的數據或信息,以保證函數的正常運行。
  • 形式參數(parameter):在函數定義的時候使用到的參數,一般沒有賦值(默認參數除外)。
  • 實參(argument):在函數調用的時候實際賦予的值。
  • 如果在函數定義時給定了形式參數,並且沒有給該參數默認值,則在調用的時候必須給定一個實參
def SayHello(person):
    print("Hi {0},nice to meet you!".format(person))
    print('Nice to meet you too!')

SayHello('TOM')

Hi TOM,nice to meet you!
Nice to meet you too!

Python參數的類型

  • 普通參數
    • 普通參數是Python函數中最常見的參數,也叫做位置參數;
    • 在函數定義的時候直接給定參數的名稱,調用時按照參數的位置賦予參數值
    • 注意,如果在一個函數中定義了多個普通參數,在調用賦值的時候,必須按照定義的順序依次賦值。
    • # Python函數的定義和調用語法
      def func_name(parameter1,parameter2,...):
            function_body
      #調用
      func_name(value1,value2,...)
  • 默認參數
    • 在函數定義的時候,給形式參數賦予一個默認值;調用函數的時候,如果沒有給該參數賦新值,則使用函數定義時的默認值
    • 如果位置參數和默認參數都存在,則必須將位置參數放在默認參數前
    • # 使用默認參數
      
      def Student(name,age,gender='male'):
          if gender == 'male':
              print("{0} is {1} years old, and he is a good student.".format(name,age))
          else:
              print("{0} is {1} years old, and she is a good student.".format(name,age))
      
      # 調用上述函數Student
      Student('WangXiaoli',20,'female')
      Student('ZhangDayong',22)
      
      WangXiaoli is 20 years old, and she is a good student.
      ZhangDayong is 22 years old, and he is a good student.
  • 關鍵字參數
    • 定義的方式和默認參數一樣,只不過像多個默認參數的集合
    • 關鍵字參數是以鍵值對的形式,再調用的時候,並不需要考慮參數的位置
    • 如果關鍵字參數函數中還有普通的位置參數,則在函數定義時,需要把普通參數放在前面。並且調用的時候,普通參數也必須放在前面
    • # 使用關鍵字參數
      def func_name(name='TOM',age=20,addr='No addr'):
          print('I am a student.')
          print("My name is {0}, and I am {1} years old, I come from {2}.".format(name,age,addr))
          
      # 調用
      # 關鍵字參數調用時,參數的位置是不重要的
      func_name(name='WangMeili',addr='China',age=23)
      # 關鍵字參數也屬於特殊的默認參數
      func_name()
      
      I am a student.
      My name is WangMeili, and I am 23 years old, I come from China.
      I am a student.
      My name is TOM, and I am 20 years old, I come from No addr.
      
      # 同普通參數的混用
      # 如果關鍵字參數函數中還有普通的位置參數,則在函數定義時,需要把普通參數放在前面
      # 調用的時候,普通參數,也必須放在前面
      # 否者就會報下面的定義錯誤
      def func_name(age,name='TOM',addr='No addr'):
          print('I am a student.')
          print("My name is {0}, and I am {1} years old, I come from {2}.".format(name,age,addr))
          
        File "<ipython-input-13-0663557d1e59>", line 5
          def func_name(name='TOM',age,addr='No addr'):
                       ^
      SyntaxError: non-default argument follows default argument
      
      # 調用錯誤
      # 強調位置參數必須放在前面
      def func_name(name,age=20,addr='No addr'):
          print('I am a student.')
          print("My name is {0}, and I am {1} years old, I come from {2}.".format(name,age,addr))
       
      # 錯誤的調用方法
       func_name(age=22,'JACK',addr='China')
      
      
        File "<ipython-input-16-e8faf29fa701>", line 7
          func_name(age=22,'JACK',addr='China')
                                               ^
      IndentationError: unindent does not match any outer indentation level

       

       

  • 收集參數
    • 把沒有名稱,也沒有位置,沒有對應關系的參數放入到一個集合中(tuple),稱為收集參數
    • 實際傳入的參數可以是任意多個,也可以沒有
    • 語法結構
      def func_name(*args):
            function_body
         按照tuple的使用方法定義*args,得到傳入的參數
      
         調用:
      func_name(p1,p2,p3,...)
      #參數名args是約定俗稱的寫法,前面必須加*
      
      
      # 使用收集參數
      # 函數模擬學生的自我介紹,介紹的內容不確定
      # args可一看作是一個元組tuple
      
      def InstroStu(*args):
          print("Hello everyone,allow me to introduce myself:")
          print(type(args))
          for params in args:
              print(params)
              
      # 調用
      # 相當於把提供的實參,裝入到args中
      InstroStu('WangMeili',18,'Nanjing','single')
      InstroStu('TOM')
      
      Hello everyone,allow me to introduce myself:: 
      <class 'tuple'>
      WangMeili
      18
      Nanjing
      single
      Hello everyone,allow me to introduce myself:: 
      <class 'tuple'>
      TOM

       

  • 收集參數之關鍵字參數
    • 與收集參數不同的是,收集關鍵字參數改善了收集參數無名稱、無對應關系的缺點。
    • 收集關鍵字參數使用字典(dict)來保存參數
    • #語法結構
      def func_name( **kwargs):
            function_body
      
      #調用:
      func_name(p1=v1,p2=v2,...)
      
      # 關鍵字收集參數
      # 自我介紹
      
      def Stu(**kwargs):
          print('Hello everyone,allow me to introduce myself: ')
          print(type(kwargs))
          # 對於字典的訪問
          for key,value in kwargs.items():
              print(key,'--->',value)
              
      # 調用
      Stu(name='wangmeili',age=19,add='Nanjing',lover='Gavin',work='Teacher')
      
      print('*' * 30)
      
      Stu(name='TOM')
      
      print('*' * 30)
      
      Stu()
      Hello everyone,allow me to introduce myself: 
      <class 'dict'>
      name ---> wangmeili
      age ---> 19
      add ---> Nanjing
      lover ---> Gavin
      work ---> Teacher
      ******************************
      Hello everyone,allow me to introduce myself: 
      <class 'dict'>
      name ---> TOM
      ******************************
      Hello everyone,allow me to introduce myself: 
      <class 'dict'>

       

  • 四種參數混合調用規則
    • 位置參數,默認參數,收集參數(tuple),關鍵字參數,收集關鍵字參數(dict)
    • 位置參數必須放在最前面,收集關鍵字參數放在最后面
    • 說明:默認參數、關鍵字參數和收集參數(tuple)的位置可以進行互換。如果收集參數在前,則其后的所有參數除了收集關鍵字參數外,都會變成關鍵字參數,若要修改參數的默認值,方法同關鍵字參數;如果收集參數在后,那么前面所有的參數除了位置參數外,都會變成默認參數,若要修改默認值,方法同默認參數。
    • 調用規則等同於定義規則
    • # 混合參數使用案例
      # 自我介紹
      
      def Student(name,age=20,*args,addr='No addr',hobby='None',**kwargs):
          print('Hello,大家好!')
          print("我叫{0},我今年{1}歲,我來自{2}".format(name,age,addr))
          
          if hobby == 'None':
              print('我目前沒有啥特別的喜好')
          else:
              print("我的愛好是{0},有興趣大家可以一起玩呀!".format(hobby))
              
          print('-' * 30)
          for i in args:
              print(i)
          print('-' * 30)    
          for k,v in kwargs.items():
              print(k,'--->',v)
          print('*' * 30)
              
              
      # 調用
      Student('豬上樹',22,'足球','籃球',addr='江蘇南京',hobby='桌球',lover='王美麗',hate='張大熊')
      Student('張大熊',25,'但是我是一個環保愛好者','也是一名公益事業愛好者',addr='南郵')
      
      
      
      Hello,大家好!
      我叫豬上樹,我今年22歲,我來自江蘇南京
      我的愛好是桌球,有興趣大家可以一起玩呀!
      ------------------------------
      足球
      籃球
      ------------------------------
      lover ---> 王美麗
      hate ---> 張大熊
      ******************************
      Hello,大家好!
      我叫張大熊,我今年25歲,我來自南郵
      我目前沒有啥特別的喜好
      ------------------------------
      但是我是一個環保愛好者
      也是一名公益事業愛好者
      ------------------------------
      ******************************

       

    • # 上例函數可以改寫為如下,將*args位置提前
      def Student1(name,*args,age=20,addr='No addr',hobby='None',**kwargs):
          print('Hello,大家好!')
          print("我叫{0},我今年{1}歲,我來自{2}".format(name,age,addr))
          
          if hobby == 'None':
              print('我目前沒有啥特別的喜好')
          else:
              print("我的愛好是{0},有興趣大家可以一起玩呀!".format(hobby))
              
          print('-' * 30)
          for i in args:
              print(i)
          print('-' * 30)    
          for k,v in kwargs.items():
              print(k,'--->',v)
          print('*' * 30)
      
      Student1('大熊',1,3,4,5,age=22,hobby='籃球',x=1,y=2,z=3)
      Hello,大家好!
      我叫大熊,我今年22歲,我來自No addr
      我的愛好是籃球,有興趣大家可以一起玩呀!
      ------------------------------
      1
      3
      4
      5
      ------------------------------
      x ---> 1
      y ---> 2
      z ---> 3
      ******************************

       

  • 兩種收集參數的解包問題
    • 不同於上面的例子,當傳入的參數不再是單個字符串或者數字時,例如傳入的是一個列表或集合或元組或者字典等
    • 當傳入的參數為上面上面4個之一時,我們需要訪問列表中的每一個元素時,就需要用到解包
    • # 調用list到 *args
      # 
      def Stu1(*args):
          print('hahahhahahha')
          for i in args:
              print(i)
              
      ll = ['wangmeili',22,'shanghai']
      # 這種調用方式,直接將整個list打印出來
      Stu1(ll)
      print('---------------')
      # 如果要將list中的每個元素都打印出來,就需要解包
      Stu1(*ll)
      hahahhahahha
      ['wangmeili', 22, 'shanghai']
      ---------------
      hahahhahahha
      wangmeili
      22
      shanghai

       

    • # 調用dict到 **args
      def Stu2(**kwargs): 
              print('hahahhahahha')
              for k,v in kwargs.items():
                  #print(type(k))
                  #print(type(v))
                  print(k,'>>>',v)
              
      d = {'name':'wangmeili','age':'22','addr':'shanghai'}
      # 此時若要將字典當作實參傳遞給kwargs,就必須先進性解包
      Stu2(**d)
      print('-------------')
      
      # 不解包傳參
      Stu2(d)
      # 不解包傳參,函數會把傳入的字典名稱d,當作一個位置參數
      hahahhahahha
      name >>> wangmeili
      age >>> 22
      addr >>> shanghai
      -------------
      
      ---------------------------------------------------------------------------
      TypeError                                 Traceback (most recent call last)
      <ipython-input-82-09f0a7d3879b> in <module>()
           13 
           14 # 不解包傳參
      ---> 15 Stu2(d)
      
      TypeError: Stu2() takes 0 positional arguments but 1 was given

       

  • 有關*args和**kwargs兩者之間的區別和其他擴展用法
    • *args就是一個無名參數的集合,沒有位置形和對應性,參數集合可以理解為一個元組tuple
    • **kwargs可以看作是一組由關鍵字參數組成的字典集合
    • 由下面的例子可以看出,在混合或非混合使用的場景中,兩種參數會自動進行分解形成相應的數據類型
    • def test(*args,**kwargs):
          print('args = ',args)
          print('kwargs = ',kwargs)
          print('--------------')
      
      test(1,2,3,4)
      test(a=1,b=2,c=3)
      test(1,2,3,4,a=1,b=2,c=3)
      test('a',None,3,a='qq',b=2,c=9)
      
      args =  (1, 2, 3, 4)
      kwargs =  {}
      --------------
      args =  ()
      kwargs =  {'a': 1, 'b': 2, 'c': 3}
      --------------
      args =  (1, 2, 3, 4)
      kwargs =  {'a': 1, 'b': 2, 'c': 3}
      --------------
      args =  ('a', None, 3)
      kwargs =  {'a': 'qq', 'b': 2, 'c': 9}
      --------------

       

    • # 將一串字符轉變為一個元組tuple
      def aas(x,*args):
          print(x)
          print(args)
          
      aas(1,2,3,4,5,6,7,'a','aa','scd')
      1
      (2, 3, 4, 5, 6, 7, 'a', 'aa', 'scd')
      
      # 使用**args 創建一個字典
      def gen_dict(**kwargs):
          return kwargs
      dict1 = gen_dict(a=1,b=2,c=3,name='jack')
      print(dict1)
      {'a': 1, 'b': 2, 'c': 3, 'name': 'jack'}

       

  最后,Python參數的定義形式雖然種類不是很多,但是使用時,尤其混合使用時一定要注意順序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM