函数
    为实现代码的重复利用,对实现某一功能的代码进行封装以实现代码抽象,方便重复调用
    python常用内置函数在builtins.py中

    1. print() # 输出
    2. type() # 返回类型
    3. id() # 返回内存地址
    4. input() # 输入
    5. len() # 返回长度
    6. open() # 打开文件
    7. round() #返回浮点数x的四舍五入值
    8. abs() # 取绝对值

    函数调用
    在Python中调用一个函数,需要知道这个函数的名称和传入参数

    1. a1 = abs(-1)
    2. print(a1) # 1
    3. a2 = abs(-1,-2)
    4. print(a2) # TypeError: abs() takes exactly one argument (2 given)
    5. a3 = abs('a')
    6. print(a3) # TypeError: bad operand type for abs(): 'str'
    7. '''
    8. 函数名其实就是指向一个函数对象的引用,完全可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”
    9. '''
    10. a4 = abs # 变量a4指向abs函数
    11. print(a4) # <built-in function abs>
    12. print(a4(-1)) # 1

    调用函数的时候,如果传入的参数数量不对,会报TypeError的错误,并且Python会明确地告诉你:abs()有且仅有1个参数,但给出了两个;
    如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报TypeError的错误,并且给出错误信息:str是错误的参数类型;
    自定义一个函数
    Python中定义一个函数,使用 def 语句,def+函数名+(参数)+: ,通过语句块缩进来编写函数体,通过 return 来返回值

    1. def add(x,y):
    2. sum = x + y
    3. return sum
    4. a = add(2,3)
    5. print(a) # 5
    6. def add(x,y):
    7. sum = x + y
    8. a = add(2,3)
    9. print(a) # None

    注:函数需要return来把数据返回给外部调用,如果不写return,函数默认return None
    函数在内部执行语句时,一旦执行到return,函数就执行完毕并把结果返回,即使return下面有同样缩进的语句块,但并不会执行

    1. def add(x,y):
    2. sum = x + y
    3. return sum
    4. print("这是函数中return后的语句") # 在调用函数时,该print语句并不会被执行

    空函数
    有确定的 def+函数名+(参数)+: ,在函数体中用 pass 代替实际的代码语句

    1. def func():
    2. pass # pass语句什么都不做,实际上 pass 通常作为代码的点位符,在程序框架 设计中常用

    返回多个值
    函数通过 return 返回单个值,同样也可返回多个值

    1. def names(x,y):
    2. name_1 = x
    3. name_2 = y
    4. return name_1, name_2
    5. n = names('Jack','Flack')
    6. print(n) # 返回('Jack', 'Flack')
    7. print(type(n)) # 返回类型 <class 'tuple'>

    Python中函数return多个值时,返回类型为 tuple(元祖),tuple中包含多个值
    任务:
    定义一个函数,传入参数为一个list, l1 = [1,2,3,4,5,6……n],对这个list 按 12+22+32.+….+n2 累加,返回这个累加值。
    函数的参数
    Python函数的定义比较灵活,除正常定义必选参数外,还可以使用默认参数、可变参数和关键字参数,在处理复杂参数的同时,方便简化调用

    1. '''定义一个函数,实现x2+1的计算'''
    2. def formula(x):
    3. return x*x+1

    对于函数 formula(x) ,参数 x 就是一个位置参数,当我们调用 func函数时,就必须传入并且只传入一个参数 x

    1. a1 = formula(3) # 参数传入3,等同于x=3
    2. print(a1) # 10
    3. a2 = formula(x=4)
    4. print(a2) # 17

    现在如果要通过函数来实现 x2+ y,在formula的参数中就需要传入x, y两个参数

    1. '''定义一个函数,实现x2+y的计算'''
    2. def formula(x,y):
    3. return x*x+y
    4. a3 = formula(3,2) # 调用formula函数时,传入的参数为3和2,按照位置相当于x=3,y=2,结果为11
    5. a4 = formula(2,3) # 调用formula函数时,传入的参数为2和3,按照位置相当于x=2,y=3,结果为7

    传参时按照参数位置填入对应参数,就属于位置参数
    默认参数
    根据 formula函数,如果实际工作中,这个函数更多的是用来计算 x2+1,但我们也需要这个函数能计算 x2+y,为了简化代码调用,可以给 y 指定一个默认参数 y=1

    1. def formula(x,y=1):
    2. return x*x+y
    3. a5 = formula(3) # 调用formula函数时,虽然只传入的参数x=3,但定义函数时默认y=1,等价于 formula(3,1)所以结果为10

    从上面例子可以看到,默认参数可以简化函数的调用
    需要注意:定义函数时,必选参数放前,默认参数放后

    1. def formula(x=3,y): # SyntaxError: non-default argument follows default argument
    2. return x*x+y

    解释器会报错:SyntaxError: non-default argument follows default argument
    可变参数
    例:当我们需要定义一个函数,实现a2+b2+c2+d2…….+n2,n为任意数

    1. def formula(*numbers): # *numbers为可变参数(numbers类型为元祖,用于接收任意个传入的参数), 即调用该formula函数时,可传入任意数量参数
    2. sum = 0
    3. print(type(numbers),numbers) # <class 'tuple'> numbers类型为元祖
    4. for i in numbers:
    5. sum += i*i
    6. return sum
    7. a6 = formula(1) # 此时可变参数numbers接收的参数是1,numbers = (1,),结果为1
    8. a7 = formula(1,2,3) # 此时可变参数numbers接收的参数是1,2,3,numbers=(1,2,3),结果为14

    如果需要传入的参数是一个list或tuple,可通过*+参数来对list或tuple解包

    1. n = [1,2,3,4]
    2. a8 = formula(*n) # *n作用是把n中的元素全部取出,放入numbers元祖中,等价于formula(1,2,3,4)

    通过 *n 把 n这个list中所有元素解包后作为可变参数传入函数,是一种常用方法
    关键字参数
    关键字参数允许传入0个或任意个带参数名的参数,这些关键字参数在函数内部以字典的形式存储

    1. '''定义一个函数,存储学生信息'''
    2. def student_info(name, age, **kw):
    3. student_name = name
    4. student_age = age
    5. key_values = kw # **kw是以字典类型来存储传入的关键字参数
    6. print("key_values类型:",type(key_values))
    7. print(student_name, student_age, key_values)
    8. a9 = student_info('Jie',18) # key_values类型: <class 'dict'>
    9. Jie 18 {}
    10. a10 = student_info('Jie',18,city='Shanghai',country='China')
    11. # key_values类型: <class 'dict'>
    12. # Jie 18 {'city': 'Shanghai', 'country': 'China'}

    把一个已声明的字典作为关键字参数传入 student_info函数,可通过 **+变量名 实现

    1. more_info = {'city': 'Shanghai', 'country': 'China'}
    2. a11 = student_info('Jie',18,**more_info)
    3. # **more_info作用是把字典more_info中的key:value解包后作为关键字参数以字典形式存入kw中

    注意:**more_info 只是对more_info拷贝,因此在函数内更改这个more_info是不会对原来的more_info产生影响的
    参数组合
    在Python中定义函数时,可以用必选参数、默认参数、可变参数、关键字参数,组合使用
    参数定义的顺序,位置参数-可变参数-默认参数-可变关键字参数

    1. def func_1(a,b,*args,c=3,**kw):
    2. print(f"参数a={a},参数b={b},可变参数args={args},参数c={c},关键字参数kw={kw}")
    3. a12 = func_1(1,2) # 参数a=1,参数b=2,参数c=3,可变参数args=(),关键字参数kw={}
    4. a13 = func_1(1,2,4,'A','B',k='D',v='E')
    5. # 参数a=1,参数b=2,参数c=4,可变参数args=('A','B'),关键字参数kw={'k': 'D', 'v': 'E'}

    小结:
    1、Python函数定义中参数形态比较灵活,可以传入复杂的参数,又方便简单调用;
    2、默认参数不能是可变对象(List),可变对象引发程序逻辑错误;
    3、可变参数 args,接收一个tuple;
    4、可变关键字参数 **kw, 接收一个dict;
    5、可变参数可直接传入:func(1,2,3),又可以通过list或tuple,再通过
    解包的方式传入:func((1,2,3));
    6、关键字参数可直接传入:func(x=1,y=2),又可以通过dict,经过*解包方式传入:func(
    {‘k’=1,’v’=1};
    7、参数组合时,参数定义顺序:位置参数-可变参数-默认参数-可变关键字参数(同学们注意下基于python参数特性,文档此处有修改)