一、什么是函数

  函数一词最早来源于数学,在编程语言中所说的函数指的是计算机函数,是指一段可以直接被另一段程序引用的程序,也叫做子程序,方法等。说的通俗一点,函数就是一堆代码的集合,这些代码能够实现特定的功能,后期如多次用到这个功能,直接调用函数名就可以实现,不用重复再写一遍代码。使用函数的好处是,能够减少重复代码,使程序变得可扩展和更加容易维护。

二、如何定义一个函数

  def 函数名(形参):

    主体代码

  调用:函数名(实参)

  其中,形参可有可无,如果函数定义时没有形参,在调用的时候也不用传实参。

def hello():
    print('hello world!')
hello()

def calculate(x, y):  # x,y 为形参
    res = x + y
    print(res)
calculate(1, 2)  # 1,2是实参
结果:
hello world!
3

  形参变量,只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。

  实参变量,可以是常量、变量、表达式、函数等,无论实参是何种类型的变量,在进行函数调用时,它们都必须有确定的值,一边把这些值传给形参变量,因此应预先给实参赋值。

三、函数的参数类型及调用方法

   函数的参数,有位置参数、默认参数、关键参数以及不定长参数。

  (1)位置参数 

def student(name,age,country):
  print(name,age,country)
student("lilei",18,"China")
student("zhangsan",39,"China")
student("lisi",20,"China")

   从上面的代码可以看出,在函数调用的时候,实参赋值与形参是一一对应的关系,是按照位置顺序进行赋值操作,这种参数称为位置参数。

  (2)默认参数

  我们看到三个学生的国籍都是“China",每次都要重复输入,有没有解决方法呢。 

def student(name,age,country="China"):
    print(name,age,country)
student("lilei",18)
student("zhangsan",39)
student("lisi",20,"Japan")

结果:
lilei 18 China
zhangsan 39 China
lisi 20 Japan

  在函数定义的时候,就给形参赋上初值,这个形参就称为默认参数,在函数调用的时候,默认参数不用赋值,默认是设置的初值;如果调用时给默认参数赋值了,则用新的值替代默认值。还有一点需要注意:默认参数在定义时一定要在位置参数之后,否则会有语法错误。

  (3)关键参数

  关键参数是在函数调用的时候,通过以“形参名”=实参 的方式进行赋值操作,需要注意:赋值时,关键参数应放在位置参数之后,关键参数的赋值顺序可以不按定义时的形参顺序进行赋值,可以任意调整位置,但前提是一定要在位置参数之后。

def student(name,age,country="China"):
    print(name,age,country)
student("lilei", age=18)
student("zhangsan", country="China", age=39)
student(country="Japan", name="lisi", age=20)
结果:
lilei 18 China
zhangsan 39 China
lisi 20 Japan

  (4)不定长参数

  不定长参数,*args和**kwargs其实分别是位置参数和关键参数的集合,可以分别传入多个位置参数和关键参数。

def student(name,age,*args,**kwargs):
    print(name,age,args,kwargs)
student("lilei", age=18)
结果:
lilei 18 () {}

  我们首先看到,如果不给不定长参数传参,args默认以元组形式呈现,kwargs以字典形式呈现。如何对不定长参数传参呢?

def student(name,age,*args,**kwargs):
    print(name, age, args, kwargs)
student("lilei", 18, "beijing", sex='male')
结果:
lilei 18 ('beijing',) {'sex': 'male'}

  我们可以看到,给不定长参数*args传参是以位置参数的方式传进去的,而给不定长参数**kwargs传参是以关键字参数的方式传入的。

  注意:当有不定长参数存在时,如果给不定长参数传参,传参时需要注意,在不定长参数之前不能出现关键字参数,比如不能出现

student("lilei", age=18, "beijing", sex='male')

  这种调用方式将age=18 放在了“beijing"之前,违反了位置参数优先于关键字参数的传参原则。所以当有不定长参数*args存在时,前边只能用位置参数的方式进行传参。