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

1. 函数介绍

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

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

1.1. 为什么要使用函数

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

降低编程难度:通常将一个复杂的大问题分解成一系列的小问题,然后将小问题划分成更小的问题,当问题细化为足够简单时,我们就可以分而治之,各个小问题解决了,大问题就迎刃而解了。

代码重用:避免重复劳作,提供效率

代码更加简洁美观,可读性增加

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)。

调用函数,那么只需要使用函数名加括号,就能执行,但如果函数定义了参数,那么必须在执行的时候传递参数给函数,否则会报异常!关于调用我们还需要了解:

函数定义,只是声明了一个函数,它不会被执行,调用时才会执行

调用方式就是函数名后加上小括号,如果有必要需要在括号内写上参数

调用时写的参数是实际参数,是实实在在传入的值,简称实参

函数是可调用对象,可以使用 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. 函数的参数

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

位置传参:按照参数定义顺序传入实参,位置参数是按位置对应的

关键字传参:使用形参的名字来传入实参的方式,如果使用了 形参的名字,那么传入参数的顺序就可以和定义的顺序不同

当位置传参和关键字传参混用时,位置参数必须在关键字参数之前传入。

# 定义函数 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,作为 关键字传参 传递给函数

这种方法在后面函数的调用过程中非常常用

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

给函数提供实参的时候,可以在集合类型前使用 * 或者 **,把集合类型的结构解开,提取出其中所有元素作为函数的实参

非字典类型使用 * 解构成位置参数

字典型使用 ** 解构成关键字参数

提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配,否则请使用 *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

总结:

Python 函数使用 return 语句返回 "返回值"

所有函数都有返回值,如果没有 return 语句,隐式调用return None

return 语句并不一定是函数的语句块的最后一条语句

一个函数可以存在多个 return 语句,但是只有一条可以被执行,如果没有一条 return 语句被执行,隐式调用return None

5.return None 可以简写为 return

函数执行到 return 就会返回,所以 return 后面的语句永远不会被执行

return 可以理解为,结束当前函数计算,返回值!

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

返回值数量 = 0,即 return(或者不写 return 语句),返回的数据为 None。

返回值数量 = 1,返回 object(一个对象)。

返回值数量 > 1,返回 tuple(一个元组)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值