Python_9_函数定义-位置参数-返回值

  • 1. 函数介绍
    • 1.1. 为什么要使用函数
    • 1.2. Python 中的函数
  • 2. 函数的基本使用
  • 3. 函数的参数
    • 3.1. 参数的缺省值
    • 3.2. 可变参数
      • 3.2.1. 可变位置传参
      • 3.2.2. 可变关键字传参
      • 3.2.3. 可变参数混合使用
      • 3.2.4. 可变参数小结
    • 3.3. keyword-only 参数 *
    • 4.1. 参数解构
  • 5. 函数的返回值

1. 函数介绍

  函数 在编程语言中就是完成特定功能的一个词句组 (代码块),这组语句可以作为一个单位使用,并且给它取一个名字。可以通过函数名在程序的不同地方多次执行(这叫 函数的调用)。函数在编程语言中有基本分为:预定义函数自定义函数。预定义函数可以直接使用,而自定义函数顾名思义需要我们自己定义函数。

在数学中的定义,这里就不介绍了。请参考 函数(数学函数)_百度百科

1.1. 为什么要使用函数

在编程中使用函数主要有两个优点:

  1. 降低编程难度:通常将一个复杂的大问题分解成一系列的小问题,然后将小问题划分成更小的问题,当问题细化为足够简单时,我们就可以分而治之,各个小问题解决了,大问题就迎刃而解了。
  2. 代码重用:避免重复劳作,提供效率
  3. 代码更加简洁美观,可读性增加

1.2. Python 中的函数

  在 Python 中,函数由 若干语句组成的代码块函数名称参数列表 构成,它是组织代码的最小单元,使用函数可以完成一定的功能,在 Python 中函数主要分为三类:内置函数第三方函数库自定义函数。常用的内置函数在前面已经介绍,第三方函数库需要先引入模块,通过模块调用,在模块学习中进行介绍,这里主要说的是如何自定义一个函数。

2. 函数的基本使用

  在 Python 中,定义一个函数要使用 def 语句,依次写出 函数名括号括号中的参数冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句 返回。下面是一个函数的基本结构:

def 函数名(参数列表):
    函数体(代码块)
    [return 返回值]   # 函数可以无返回值

注意:

  • 函数名 就是 标识符,命名要求一样
  • 语句块 必须缩进,约定 4 个空格
  • Python 的函数可以没有 return 语句,会隐式地返回一个 None
  • 定义中的参数列表称为形式参数,只是一种符号表达式(标识符),简称 形参

  我们以自定义一个求绝对值的函数为例:

In : def abs(x):
...:     if x >= 0:
...:         return x
...:     else:
...:         return -x
...:

In : abs(-10)
Out: 10

In : abs
Out: 

In : print(abs)

  上面只是一个函数的定义,具体来看一下各个部分的解释:

  • 函数名字叫做 abs,接受 1 个形式参数 x。
  • return x: 表示要返回的值是 x,函数可以无返回值。
  • 函数是一个 可调用对象,函数名 加括号 就表示调用。
  • 和变量的使用方式相同,在使用函数时,需要预先进行定义。
  • 直接打印函数名,不会触发函数的执行,反而会打印函数的内存地址。

  我们自定义的函数 abs, 由于与内置函数重名,那么将会覆盖掉内置函数,所以请谨慎命名。

  函数体内部的语句在执行时,一旦执行到 return 时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。如果没有 return 语句,函数执行完毕后会隐式地返回 None。如果我们确实要 return None 可以简写为 return,或者不写 return 语句 (会让人看不懂,建议只写 return)。
  调用函数,那么只需要使用函数名加括号,就能执行,但如果函数定义了参数,那么必须在执行的时候传递参数给函数,否则会报异常!关于调用我们还需要了解:

  1. 函数定义,只是声明了一个函数,它不会被执行,调用时才会执行
  2. 调用方式就是函数名后加上小括号,如果有必要需要在括号内写上参数
  3. 调用时写的参数是实际参数,是实实在在传入的值,简称实参

函数是可调用对象,可以使用 callable() 进行判断

In : def abs(x):
...:     if x >= 0:
...:         return x
...:     else:
...:         return -x

# 函数是可调用的,注意这里不能对函数加括号,那么 callable 判断的就是函数的返回值是否可以执行了
In : callable(abs)     
Out: True

# 字符串是不可调用的
In : a = '123'
In : callable(a)    
Out: False

3. 函数的参数

  定义函数的时候,括号中指定的就是函数的参数 (形式参数),当我们调用函数时,需要将数据进行传递,这种传递参数的方式就叫做传参,严格来说函数只可以使用两种方式:位置传参关键字传参

  1. 位置传参:按照参数定义顺序传入实参,位置参数是按位置对应的
  2. 关键字传参:使用形参的名字来传入实参的方式,如果使用了 形参的名字,那么传入参数的顺序就可以和定义的顺序不同
  3. 位置传参关键字传参混用时,位置参数必须在关键字参数之前传入
# 定义函数 function:
In : def function(x, y):
...:     result = x + y
...:     return result
...:

# 位置传参: # 1 对应 x,2 对应 y。
In : function(1, 2)    
Out: 3

# 关键字传参: 使用关键字时,参数可以不用按照位置顺序。
In : function(y=1, x=2) 
Out: 3

# 混合传参: 混用时,关键字参数必须要再位置参数右边
In : function(1, y = 3) 
Out: 4

3.1. 参数的缺省值

  在定义形式参数时,为参数指定对应的值,就叫做参数的缺省值,当定义了参数的缺省值以后,我们传参时可以选择传递该参数的值,也可以选择不传递,当 不传递 此参数的值时,该参数就使用指定的 缺省值否则 将会使用 传递的值

参数缺省值也属于位置参数,只不过是给位置参数定义了默认值。

In : def function(x = 10, y = 20):
...:     return x + y
...:

# 2 会以位置参数的形式传递给 x,y 没有传递,会使用缺省值
In : function(2)   
Out: 22

# x 没有传递,会使用缺省值
In : function(y=100)  
Out: 110

# y 没有传递,会使用缺省值
In : function(x=100)  
Out: 120

# 20 以位置参数的形式传递给 x,500 以关键字参数的形式传递给了 y
In : function(20, y=500)  
Out: 520

当定义参数的缺省值时,注意 缺省值参数 必须要放在 位置参数的右边

# 必须把 x=1,放在 y 的右边,否则无法完成函数定义
In : def functions(x=1, y):    
...:     print(x+y)
  File "", line 1
    def functions(x=1, y):
                 ^
SyntaxError: non-default argument follows default argument

使用缺省值参数的好处是:

  • 参数的缺省值可以在未传入足够的实参的时候,对没有给定的参数赋值为缺省值。
  • 参数非常多的时候,并不需要用户每次都输入所有的参数,简化函数调用。

3.2. 可变参数

  可变参数顾名思义表示参数的数量是可变的,并且可以使用一个形参匹配任意个实参。针对传递参数方式的不同又分为 可变位置传参可变关键字传参

3.2.1. 可变位置传参

  在形参前使用 * 号,表示该形参是可变参数,可以接受多个实参,在函数内部,可变参数会封装成元组 (即便是没有传递)

In : def function(*nums):
...:     print(nums)
...:

In : function(1,2,3,4)  # 多个参数会被 nums 收集
(1, 2, 3, 4)

In : function([1,2,3,4])  # 会把 list 收集成元组内的一个元素
([1, 2, 3, 4],)

在函数定义时,一般的规范是使用 *args, 表示收集多个位置传参。

3.2.2. 可变关键字传参

  在形参前使用 ** 号,表示该形参是可变关键字参数,可以接受多个关键字参数,在函数内部,可变关键字参数会封装成字典 (即便是没有传递)

In : def function(**kwargs):
...:     print(kwargs)
...:

In : function(a=1,b=2)
{'a': 1, 'b': 2}

# 参数的缺省值和位置参数同时使用
In : def function(x=1, y=2, **kwargs):
...:     print('x = {}'.format(x))
...:     print('y = {}'.format(y))
...:     print(kwargs)
...:

# 参数没有 a,b 形参,则被 kwargs 接收
In : function(a=10, b=20)   
x = 1
y = 2
{'a': 10, 'b': 20}

# z 没有被匹配,被 kwargs 接收
In : function(x=100,y=200,z=300) 
x = 100
y = 200
{'z': 300}

# 前面的按照位置参数赋值,z 同样被字典 kwargs 收集
In : function(1000,2000,z=300)  
x = 1000
y = 2000
{'z': 300}

3.2.3. 可变参数混合使用

  前面说的各种参数是可以混合使用的,当混合使用时遵循一定的顺序,简单总结一下,按照从左至右的顺序来说:位置参数,缺省值参数,可变位置参数,可变关键字参数:
def function(位置参数,缺省值参数,可变位置参数,可变关键字参数):
  无论如何,顺序不能颠倒

# x,y,z 都为位置参数,z 的缺省值为 1,*args 收集额外的位置传参,**kwargs 收集额外的关键字传参
In : def function(x,y,z=1,*args,**kwargs):  
...:     print(x,y,z)
...:     print(args)
...:     print(kwargs)
...:

In : function(1,2,3,4,5,a=1,b=2)
1 2 3
(4, 5)
{'a': 1, 'b': 2}

3.2.4. 可变参数小结

  针对可变参数以及不同的混用方式可以有如下结论:

  • 分为 可变位置参数可变关键字参数
  • 可变位置参数在形参前使用 一个星号 *
  • 可变关键字参数在形参前使用 两个星号 **
  • 可变位置参数可变关键字参数都可以收集若干个实参,可变位置参数 收集形成一个 tuple可变关键字参数 收集形成一个 dict
  • 混合使用参数的时候,在定义阶段要遵循如下顺序:位置参数缺省值参数可变位置参数可变关键字参数

  当位置传参和关键字传参同时使用时,针对同一个形参不可以重复赋值!,这一点使用的时候很重要。

3.3. keyword-only 参数 *

  Python3 的函数参数中,新增了 keyword-only 参数,什么叫 keyword-only 参数? 当在一个星号参数 (可变位置参数) 后,出现的普通参数,我们称它为 keyword-only 参数,因为多余的位置参数都会被 *args 收集,只能通过 keyword 的方式对这些形参进行赋值,所以它们只能使用 关键字传参

# x,y 是 keyword-only 参数,其中 y 存在缺省值,可以不用传递,x 必须使用关键字的方式进行传递
In : def function(a, b, c=1, *args, x, y=2, **kwargs):     
...:     print(a,b,c)
...:     print(args)
...:     print(x,y)
...:     print(kwargs)
...:

In : function(100,200,300,400,d=100,e=200)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
 in 
----> 1 function(100,200,300,400,d=100,e=200)

TypeError: function() missing 1 required keyword-only argument: 'x'

In : function(100,200,300,400,d=100,e=200,x=500)
100 200 300
(400,)
500 2
{'d': 100, 'e': 200}

特殊形式:

In : def function(*, x, y):   
...:     print(x,y)
...:

In : function(1, 2, 3, x=100, y=200)
---------------------------------------------------------------------------
TypeError                                 Traceback(most recent call last)
 in 
----> 1 function(1,2,3,x=100,y=200)

TypeError: function() takes 0 positional arguments but 3 positional arguments(and 2 keyword-only arguments) were given

In : function(x=100, y=200)
100 200

这里 * 表示不接受位置传参,只能使用关键字对参数进行赋值

  注意: 使用了 keyword-only 参数,那么在定义形参时的顺序就有所改变了,它们是:位置参数,缺省值参数,可变位置参数,keyword-only 参数,可变关键字参数

4.1. 参数解构

前面我们说过 Python 的封装与结构,这里的参数也可以利用这种思想进行解构,现有如下函数:

In : def add(x=1, y=2):
...:     print(x+y)
...:

# 将元组的元素 1 和元素 2 分别传给 x,y
In : t = (10,20)
In : add(t[0], t[1])   
30

# 非字典类型使用 * 解构成位置参数
In : add(*t)  
30

# 字典型使用 ** 解构成关键字参数
In : d = {'x':100, 'y':200}
In : add(**d)
300
  • 将 t 在传递参数时解构为10,20,作为位置传参 传递给 add 函数
  • 将 d 在传递参数时解构为 x=100,y=200,作为 关键字传参 传递给函数
  • 这种方法在后面函数的调用过程中非常常用

  现在再来回头看一下,什么时参数解构?

  1. 给函数提供实参的时候,可以在集合类型前使用 * 或者 **,把集合类型的结构解开,提取出其中所有元素作为函数的实参
  2. 非字典类型使用 * 解构成位置参数
  3. 字典型使用 ** 解构成关键字参数
  4. 提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配,否则请使用 *args,**kwargs
In : def add(a,b,*args,m,n,**kwargs):
...:     print(a + b + m + n)
...:

In : dic = {'a':100,'b':200}
In : add(**dic,m=300,n=400,x=1000)
1000

5. 函数的返回值

  我们通常编写函数除了代码可以复用,更多的时候需要的是知道函数的运算结果,函数把运算的结果返回给我们,这个结果就叫作做函数的返回值。使用 return 关键字进行返回。

# 返回 1 个数据
In : def add(x,y):
...:     result = x + y
...:     return result
...:

In : a = add(10,20)
In : print(a)
30

# 返回多个数据
In : def add(x,y):
...:     result = x + y
...:     test = x * y
...:     return result,test
...:

In : a = add(10,20)
In : print(a)
(30, 200)

# 多个 return 语句
In : def bigger(x,y):
...:     if y > x:
...:         return y
...:     else:
...:         return x
...:

In : a = bigger(10,20)
In : print(a)
20

总结:

  1. Python 函数使用 return 语句返回 "返回值"
  2. 所有函数都有返回值,如果没有 return 语句,隐式调用return None
  3. return 语句并不一定是函数的语句块的最后一条语句
  4. 一个函数可以存在多个 return 语句,但是只有一条可以被执行,如果没有一条 return 语句被执行,隐式调用return None
    5.return None 可以简写为 return
  5. 函数执行到 return 就会返回,所以 return 后面的语句永远不会被执行
  6. return 可以理解为,结束当前函数计算,返回值!

函数永远只能返回一个数据

  1. 返回值数量 = 0,即 return(或者不写 return 语句),返回的数据为 None
  2. 返回值数量 = 1,返回 object(一个对象)。
  3. 返回值数量 > 1,返回 tuple(一个元组)。

你可能感兴趣的:(Python_9_函数定义-位置参数-返回值)