zoukankan      html  css  js  c++  java
  • 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参数的定义形式虽然种类不是很多,但是使用时,尤其混合使用时一定要注意顺序。

  • 相关阅读:
    Java NIO类库Selector机制解析(上)
    SWT Display.getDefault() 和Display.getCurrent()的区别
    VSS 2005 复位 工作目录(Reset Working Folder)
    转:理解javascript中的delete机制(2)
    在 .NET Framework 2.0 中未处理的异常导致基于 ASP.NET 的应用程序意外退出
    CSS样式
    Character Animator不显示NDI无法OBS直播
    【LoadRunner】基础使用教程:录制第一个脚本(包含遇到的错误问题解决)
    流式传输 之四流式协议
    全局变量,静态变量,局部变量
  • 原文地址:https://www.cnblogs.com/Clonglegs/p/9564873.html
Copyright © 2011-2022 走看看