函数基础

函数

主要内容

  • 函数的定义
  • 函数的返回值
  • 函数的参数

函数的定义

  在Python中,我们可以在任何地方直接调用内置方法len求一个容器类型(可迭代类型)的元素个数,这个内置方法len就是一个函数。函数就是一段封存了固定代码的代码段,函数具有特定的功能,当我们调用函数,它就会执行,然后完成我们的任务。注意函数在定义后只是保存到内存中,只有我们主动通过函数名+括号的方式去调用它,函数才会执行内部代码。函数的定义方式是通过关键字def定义的,具体形式如下所示:

def get_sum(a, b):
    """求和"""
    print(a, b)
    return a+b

  可以看出函数定义的时候必须指定函数名,然后加上一对括号,里面可以传入参数,也可以不传参数,接着加上冒号,同if with while等一样,接下来缩进的代码属于函数体,属于这个函数,里面实现函数的具体功能,最后可以有返回值,可以返回给调用者。

  值得注意的是函数在定义的时候解释器只会检测语法的错误,不会执行检测内部的逻辑错误。函数的调用方式前面也说过了,就是通过函数名加一对小括号和参数

调用,如此可见函数名其实同变量一样,都相当于一个引用,指向一段内存地址,只不过函数更复杂罢了。

函数的返回值

  刚刚说完了函数的简单定义方式,接下来总结下函数的返回值情况。python中的函数返回值有多种情况,但无论怎样,要记住Python的函数一定是有返回值的。

  1.  当函数执行结束后,整个函数体都没有出现return关键字,那么函数会默认返回None

  2.  函数的某处只写了return关键字,那么此时函数也会返回None,这里的return一般带有主动结束函数的作用,例如这里的return语句处于多层循环中,就不用麻烦的break跳出循环了,只需要return语句就能中断。

  3.  函数可以返回一个值或多个值,Python中的函数可以返回任意数据类型,其中只返回一个值时,Python不会做处理,当返回一个以上的值时,会把这多个值打包成一个元组返回给调用者,这里用元组一个是因为不可变,还有就是元组相对其他容器类型更节省内存。

def get_sum(a, b):
    """求和"""
    return a, b, a + b
print(get_sum(1, 2))
(1, 2, 3)

函数的参数

参数的概述

  函数定义的时候,括号里写的类似变量的就是函数的参数,叫作形式参数,简称形参,在我们调用函数的时候,也需要给函数传参数,这时候传的参数就叫做实际参数,简称实参。实参和形参的关系可以这么理解,形参在函数定义的时候就只是个变量名,还没有任何意义,当我们传入实参给函数的时候,这时候实参就相当于值,并赋值给形参。

  函数定义时的形式参数也比较复杂,主要分为以下几种类型。

参数的类型

  1.  位置参数

  所谓位置参数就是函数定义时,只有变量名表示的参数位置,就是def(a, b)这样的形式定义的,这里a,b就是位置参数,以位置参数定义的时候,我们调用的时候也必须保证传入的时候一一对应,且传入实参不能多也不能少,否则都会抛出异常。

def test(a, b):
    print(a, b)


test(2, 4)
test(b=4, a=2)
test(2, b=4)
test(b=4, 2)    # positional argument follows keyword argument

  作为调用者,传入方式主要有以上几种,第一个就是按照参数的具体意义一一对应传入,正如其名位置参数一样。第二个就是可以使用关键字参数传参数,这时候可以不用与形参变量名的位置一一对应,但是传入的参数还必须一样多。第三种就是关键字参数可以和位置参数混合传入给形参,此时需要注意的点就是位置参数必须在前面,否则就会报错。就像上面最后一个测试例子一样。

  2. 默认参数

def line(x, a=1, b=0):
    """求线性函数的值"""
    return a * x + b


print(line(1))
print(line(1, 2))
print(line(1, 2, 3))
1
2
5

  默认参数就是函数在定义的时候默认参数就已经初始化好了,默认参数已经指向了一处内存空间了,然后就不会外界因素改变指向地址了。默认参数的特性是调用者传值后,会使用调用者传的实参的值,否则就会使用默认值。效果就如同上面的例子一样。

  下面是一个默认参数的小坑

m = 10

def func(x=m):
    print(x)

func()  # 输出是10
m = 20
func()  # 输出同样是10

  这里的核心就是要理解默认参数在定义时就指向了整数10所在的内存地址,m变量也只是一个整数10的其中一个引用,下面m重新赋值只是重新指向了20的内存地址,与默认参数x无关,所以上面的输出都是10.

  3. 可变长参数

  所谓可变长,就是指代调用者可以传入不定长个参数给函数。Python中可变长参数分为2种,一个可变长位置参数,还有就是可变长关键字参数。它们都是通过 * 号这个运算符来实现的,其中可变长位置参数的写法是变量名前面加一个 * 号, 可变长关键参数是变量名前面加两个 * 号,不过这两种参数一般都是有Python推荐的固定名称的,就是*args,和**kwargs。

  它们的功能就是 :

  * args 能够接收调用者传给函数多余的位置参数,并以元组的形式接收。

  **kwargs 能够接收调用者多余的关键字参数,并以字典的形式接收。

def func(a, *args, **kwargs):
    print(a, args, kwargs)


func(1, 2, 3, 4, name='jack', price=100)
1 (2, 3, 4) {'name': 'jack', 'price': 100}

  上面的例子就是把多余的2, 3, 4位置参数给打包成元组传递给形参了,而两个关键字最后也确实是 以字典的形式呈现的。

  此处再补充一个* 和 ** 运算符的特殊用法,就是它们可以解压打散对应的容器类型,然后把每一个实参传入函数中。

 

def func(a, *args, **kwargs):
    print(a, args, kwargs)

func(1, *'str', **{'name': 'egg', 'price': 20})
1 ('s', 't', 'r') {'name': 'egg', 'price': 20}

  效果与上述一个个传一样。

posted @ 2019-07-09 20:41  yscl  阅读(119)  评论(0)    收藏  举报