函数

定义:函数就是将一段具有独立功能的代码块,整合到一个整体并命名,在需要的位置调用这个名称即可完成调用
作用:在开发过程中,可以更高效的实现代码重用
定义函数:def 函数名(参数):代码......
调用函数:函数名(参数)
    注意:不同需求中,参数可有可无,且在Python中,函数必须先定义后使用
函数说明文档:定义:def 函数名(参数):
                      """说明文档的位置"""
                      代码......
            查看:help(函数名)
注意:函数可以实现嵌套
# 定义一个函数,实现加减乘除功能
def add(a, b):
    return a + b
def rem(a, b):
    """实现两个数之间的减法操作"""  # 说明文档 所在位置
    return a - b
i = 3
j = 8
print(add(i, j))
print(rem(i, j))
help(rem)

# 函数嵌套:实现一元二次方程的解法
a = int(input('请输入二次项系数:'))
b = int(input('请输入一次项系数:'))
c = int(input('请输入常数项系数:'))
import math
def func1(a, b, c):
    m = b**2-4*a*c
    return math.sqrt(m)
der = func1(a, b, c)
k1 = (-b+der)/(2*a)
k2 = (-b-der)/(2*a)
print(f'该一元二次方程的根为{k1}和{k2}')

函数细节

变量作用域:变量生效的范围,包括两个部分:局部变量和全局变量
    注意:函数体内同名变量名对函数体外变量名具有覆盖作用,故若想在函数体内修改全局变量须加一句:global 变量名

多函数程序执行流程

函数的返回值
    1、函数执行到return时,就会退出当前函数,无论后面是啥都不在运行
    2、可返回多个数值:return a, b写法,返回多个数据的时候,默认是元组数据
    3、return后面可以连接列表、元组或字典,以返回多个值

函数的参数
    1、位置参数:调用函数时根据函数定义的参数位置来传递参数(即形式参数),即调用时按顺序赋值

    2、关键字参数:函数调用,通过“键=值”形式加以指定,可以让函数更加清晰,同时也清除了参数的顺序需求
        注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序

    3、缺省参数:默认参数,用于定义函数,为参数提供默认值(直接在形参时定义)。

    4、不定长参数:也称可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用包裹(packing)
        位置参数,也可以用包裹关键字参数
# 全局变量的修改
# a = 1
# def con():
#     global a  # 注意这条语句存在与否的差别
#     a = 100
# con()
# print(a)
#
# # return返回多个元素
# def return_num():
#     # return 1, 2  # 返回多个返回值
#     return [12, 45, 66, 'qiao', 'long']
#
# result = return_num()  # 也可以用两个变量返回接收
# # result1 ,result2 = return_num()
# print(result)  # 元组形式
# # print(result1)
# # print(result2)
#
# # 函数的参数
# # 关键字参数
# def use_info(name, age, gender):
#     print(f'您的名字是{name},您的年龄是{age},您的性别是{gender}')
# # use_info('Lily', 24, 'woman')  # 关键字参数可以不按形参顺序
# use_info(gender='woman', name='Lily', age=18)
#
# # 缺省参数,即默认参数
# def user_m(name,age=18,gender='woman'):
#     print(f'name:{name}, age={age}, gender={gender}')
#
# user_m('Lily')
# user_m('Jane',age=20)

# 不定长参数:包裹位置传递
def user_k(*li):
    print(li)

user_k('Tom')
user_k('Tom', 24)  # 会根据传进参数的位置合并成一个元组

# 不定长参数:包裹关键字传递
def user_k2(**key):  # 注意这里两个 * 号
    print(key)

user_k2(name='Tom',age=18,gender='woman')  # 根据传进参数合成字典

# 无论是包裹位置传递,还是包裹关键字传递都是一个组包的过程

拆包和交换两个变量

拆包:字典,对字典进行拆包,取出来的是字典的key
# 对字典进行拆包
dic1 = {'name':'Lily','age':24}
n, m =dic1
print(n,m)  # 所得到的是字典的关键字
print(dic1[n],dic1[m])

a = 1
b = a

b = 10
print(id(a))
print(id(b))

引用

值是靠引用来传递的,我们可以用id()来判断两个变量是否为同一个值的引用(即id值可以理解为那块内存的地址标识)
    注意:对于赋值语句(例如:aa = bb,当bb变化时,aa是否跟随变化?)
            答:取决于aa和bb是什么数据类型,当其是不可变数据类型时,不会发生变化,id不在相同
                当其是可变数据类型时,aa会跟随变化,且aa和bb的id值依旧相同

可变和不可变类型(总结)

可变数据类型:列表、字典、集合
    不可变数据类型:整型、浮点型、字符串、元组