函数的定义、参数及参数解构

Python函数

  • 由若干语句组成的语句块、函数名称、参数列表构成,它是组织代码的最小单元
  • 完成一定的功能
  • 函数也是一个对象

函数的作用

  • 结构化编程对代码的最基本的封装,一般按照功能组织一段代码
  • 封装的目的为了复用,减少冗余代码
  • 代码更加简洁美观、可读易懂

函数的分类

  • 内建函数,如max()、reversed()等
  • 库函数,如math.ceil()等

函数的定义、调用

  • 函数的定义
    • def语句定义函数
      def 函数名(参数列表):
      函数体(代码块)
      [return 返回值]
    • 函数名就是标识符,命名要求一样
    • 语句块必须缩进,约定4个空格
    • Python的函数可以没有return语句,如果没有,隐式会返回一个None值;return语句也不一定放在最后
    • 定义中的参数列表成为形式参数,只是一种符号表达,简称形参,可以类似地理解为占位符一样的存在
  • 函数的调用
    • 函数定义,只是声明了一个函数,它不会被执行,需要调用
    • 定义需要在调用前,也就是说调用时,已经被定义过了,否则抛NameError异常
    • 调用的方式,就是函数名加上小括号,括号内写上参数
    • 函数是可调用的对象,判断是否可调用:callable()
    • 调用时写的参数是实际参数,是实实在在传入的值,简称实参

函数参数

  • 函数定义时,形参有两种形式:位置参数和可变参数
  • 位置参数
    • 定义函数def(x, y, x),调用使用f(1, 2, 3),这种函数定义和调用时使用的参数叫做位置参数
    • 按照形参定义的顺序一个一个匹配传入实参
    • 如果函数定义的时候,形参的部分不是可变参数,那么这部分参数就是位置参数
  • 关键字参数
    • 定义函数 def(x, y, z),调用使用f(x=1, y=2, z=3),这种调用时使用的参数叫做关键字参数
    • 使用形参的名字来传入实参的方式,如果使用了形参的名字,那么传参顺序就可以和定义的顺序不同
  • 传参
    • 在函数调用实参传参的时候要求:位置参数必须在关键字参数之前传入,位置参数是按位置对应的
    • f(z=None, y=10, x=[1])
    • f((1, ), z=6, y=4.1
    • f(y=5, z=6, 2) # 这种写法是绝对错误的
  • 函数定义时形参的默认值
    • 定义时,在形参后跟上一个值
    • 定义时,这部分形参如果不是可变参数,那么还是位置参数,只不过是多了一个默认值
    • 参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值
    • 参数非常多的时候,并不需要用户每次都输入所有的参数,简化函数调用
    • 定义函数的时候,没定义缺省值的形参要放在定义缺省值的前面
    • def add(x=4, y=5):
      	return x+y
      # 测试调用
      print(add()) # 
      '''输出:9'''
      
      print(add(6)) # 6是位置参数,按顺序将6传参给x;y没传参,取缺省值
      '''输出:11'''
      
      print(add(y=6)) # x没传参,取默认值4;y=6是关键字参数,将6传参给y
      '''输出:10''' # 
      
      print(add(6, y=7)) # 6是位置参数,7是关键字参数
      '''输出:13'''
      
      add(6, 10) # 
      '''输出:16'''
      
    • # 定义一个函数login,参数名称为host、port、username、password
      def login(host,  password, port=22, username='root', ):
      	return '{}@{}:{} --password {}'.format(username, host, port, password)
      
      print(login('127.0.0.1', 'root_passwd', 23))
      print(login('127.0.0.1', 'barry_passwd', username='barry'))
      
      '''输出:
      root@127.0.0.1:23 --password root_passwd
      barry@127.0.0.1:22 --password barry_passwd
      '''
      

可变参数

  • 位置参数的可变参数
    • 在函数定义时,形参前使用*表示该形参是位置参数的可变参数,可以接收多个实参 ,*形参就是一个标识符
    • 如果函数定义时,形参中包含了位置参数的可变参数,要么不给它传参,要么在函数调用传参的时候使用位置参数给这部分形参进行传参
    • 收集多个实参为一个tuple
    • def add(*nums):
      	print(nums, type(nums))
      	sum = 0
      	for i in nums:
      		sum += i
      	return sum
      
      print(add(5, 6, 7))
      print('~~~~~~')
      print(add())
      
      '''输出:
      (5, 6, 7) <class 'tuple'>
      18
      ~~~~~~
      () <class 'tuple'>
      0
      '''
      
  • 关键字参数可变参数
    • 在函数定义时,形参前使用**符号,表示可以接收多个关键字参数
    • 如果在函数定义的时候,形参部分包含了关键字参数的可变参数,要么不它传参,要么在函数调用传参的时候使用关键字参数给这部分形参进行传参
    • 收集的实参名称和值组成一个字典
    • def showconfig(**kwargs):
          print(kwargs)
          for k, v in kwargs.items():
              print( '{} = {}'.format(k, v))
      
      
      showconfig(host='127.0.0.1', port=22, username='root', password='root_passwd')
      
      '''输出:
      {'host': '127.0.0.1', 'port': 22, 'username': 'root', 'password': 'root_passwd'}
      host = 127.0.0.1
      port = 22
      username = root
      password = root_passwd
      '''
      
  • 两种可变参数混合使用
    • 混合参数在函数定义时的使用原则:
      - 形参中,位置可变参数需要在关键字可变参数之前
    • def fn(x, y, *args, **kwargs):
          print(x)
          print(y)
          print(args)
          print(kwargs)
      fn(3,5,7,9,10,a=1,b='barry')
      print('~~~~~~')
      fn(3,5)
      print('~~~~~~')
      fn(3,5,7)
      print('~~~~~~')
      fn(3,5,a=1,b='barry')
      print('~~~~~~')
      # fn(7,9,y=5,x=3,a=1,b='barry') # 错误:7和9分别赋给了x,y,又y=5、x=3,重复了,会抛TypeError: fn() got multiple values for argument 'y'异常
      
      '''输出:
      3
      5
      (7, 9, 10)
      {'a': 1, 'b': 'barry'}
      ~~~~~~
      3
      5
      ()
      {}
      ~~~~~~
      3
      5
      (7)
      {}
      ~~~~~~
      3
      5
      ()
      {'a': 1, 'b': 'barry'}
      ~~~~~~
      TypeError: fn() got multiple values for argument 'y'
      '''
      

keyword-only参数(Python3加入)

  • 函数定义时候,如果可变参数后面定义了位置参数,那么给这部分位置参数进行传参的时候,必须使用关键字参数进行传参,如果这部分位置参数有默认值,可以不传参,使用默认值
  • 如果在函数定义时的形参中,使用了*,那么在表示在*后必须使用keyword-only参数,*只是作为强制使用keyword-only参数的符号,不是形参
  • args可以看做截获了所有的位置参数,后面的形参如果不使用关键字进行传参,就不能拿到实参
  • def fn(*args, x):
        print(x)
        print(args)
    '''fn(3, 5)''' # 抛异常:TypeError: fn() missing 1 required keyword-only argument: 'x'
    '''# fn(3, 5, 7)''' # 抛异常:TypeError: fn() missing 1 required keyword-only argument: 'x'
    fn(3, 5, x=7)
    
    
    '''输出:
     7
    (3, 5)
    '''
    

可变参数和默认值

  • def fn(x=5, **kwargs) # 因为x=5在函数定义时使用的是位置参数定义,只不过是多了一个默认值,所以在函数调用传参的时候可以使用位置参数传参,也可以使用关键字参数传参,只要找到x传参了就行,没找到就使用默认值
        print(x)
        print(kwargs)
    print(y=7, x=4)
    
    '''输出:
    4
    {'y': 7}
    '''
    

参数的规则

  • 形参列表的参数一般顺序是:普通参数、缺省参数、可变位置参数、keyword-only参数(可带缺省值)、可变关键字参数
  • def fn(x, y, z=3, *arg, m=4, n, **kwargs):
    print(x,y,z,m,n) 
    print(args) 
    print(kwargs)
    

参数的解构

  • 给函数提供实参的时候,可以在集合类型前使用*或者**,把集合类型的结构解开,提取出所有的元素
  • 元素作为函数的实参
  • 非字典类型使用*解构成位置参数
  • 字典类型使用**解构成关键字参数
  • 提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配
  • def add(x, y):
        return x+y
    
    
    print(add(*(4, 5)))
    print(add(*[4, 5]))
    print(add(*{4, 5}))
    print(add(**{'x':4, 'y':5}))
    '''输出:
    9
    9
    9
    9
    '''
    
  • def sum_1(*args, **kwargs):
        result = 0
        for i in args:
            result += i
        return i
    
    print(sum_1(*range(5)))
    print(add(*[1, 2, 3, 4, 5, 6]))
    
    '''输出:
    10
    21
    '''
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值