函数

1.函数的介绍

函数:实现某个功能的代码段

函数的作用:可以对功能代码进行服用,减少代码的冗余

 

 

2.函数的定义和调用

函数定义的语法格式
  def 函数名():
  实现某个功能的一段代码

提示:函数定义完成以后,不会主动调用函数里面的功能代码,需要程序员手动调用函数,才会执行函数里面的代码
调用函数的语法格式
  函数名()
def show():
    # 遍历range时,数据不需要使用,可以使用下划线进行占位。
    for _ in range(3):
        print("人生苦短,我用python!")


# 调用函数,执行函数里面的功能代码
show()
print("xxxxx" * 10)
show()
 
 

 

3.函数的文档说明

函数的文档说明:把多行注释放到了函数内的第一行,该注释称为是文档说明

函数文档说明的作用:对函数的功能进行解释说明,告诉开发者函数的功能职责是什么

import random


def show_info():
    """我是函数的文档说明"""
    print("哈哈,今天学习了函数,好开心!")


# 查看函数的文档说明,可以使用help函数
# help(要查看的函数名)
# help(show_info)
help(random.randint)


# 补充:

def sum_num(num1, num2):
    """
    实现对两个数字完求和操作
    :param num1: 第一个数字
    :param num2: 第二个数字
    :return: 求和的数据
    """
    result = num1 + num2
    return result

 

 

4.带有参数的函数

带有参数的函数的语法格式
def 函数名(形参1, 形参2, ...):
实现相关功能的代码

函数名(实参1, 实参2, ...)

形参:在定义函数时设置的参数称为形参
实参:在调用函数时设置的参数称为实参

提示:函数定义时设置形参的目的是在调用函数时需要接收实参。
# 带有参数的函数
def sum_num(num1, num2):
    result = num1 + num2
    print("结果为:", result)


sum_num(10, 30)
print("over")

# 总结:
# 带有参数的函数,只需要在定义函数时设置形参即可
# 函数的执行流程

 


5.带有返回值的函数
带有返回值的函数的语法格式
  def 函数名():
  实现代码
  return 数据 # 这里返回的数据就是返回值

因为函数调用后有返回值,需要使用变量保存这个返回值
  result = 函数名()
  print(result)
def sum_num(num1, num2):
    value = num1 + num2
    # print("函数内使用value,该数据为:", value)
    # 通过return 把函数内的value返回给调用者
    return value


# 使用result变量,来保存sum_num函数调用后返回的结果
result = sum_num(1, 2)
print("函数返回的结果为:", result)

 


6.python提供的内置函数
内置函数:不需要导入模块或者包直接使用的函数,称为内置函数
len: 统计容器类型中元素的个数 ***
max: 返回容器类型中的最大值
min: 返回容器类型中的最小值
del: 删除指定的变量,一旦删除完成以后,后续再次使用这个变量名
my_list = ['A', "C", "E"]
# 使用变量保存len函数调用后的结果
result = len(my_list)
print("列表中元素的个数为:", result)

my_tuple = (1, 0, 5)
max_value = max(my_tuple)
print("返回的最大值为:", max_value)

min_value = min(my_tuple)
print("返回的最小值为:", min_value)

my_name = "李四"
print(my_name)
# 删除指定变量
# del(my_name)
# 提示:删除指定变量还可以通过del关键字来完成
del my_name
print(my_name)

 


7.函数的嵌套调用
函数的嵌套调用:在一个函数内部再次调用其他函数的格式。
总结: 不管直接调用还是嵌套调用函数,函数的执行流程不变。

函数的执行流程:
  1.当调用函数时,先回到函数的定义,给函数的形参赋值
  2.当形参赋值完成以后,会执行函数里面的代码
  3.当函数里面的代码执行完成以后,表示函数执行结束,代码会回到之前函数调用的地方,然后代码在继续往下
  执行。

def task1():
    print("task1函数开始执行啦...")
    print("task1")
    print("task1函数执行结束啦...")


def task2():
    print("task2函数开始执行啦...")
    # 调用task1
    task1()  # 这里就使用了函数的嵌套调用
    print("task2")
    print("task2函数执行结束啦...")


task2()

 


8.局部变量
局部变量: 在函数内定义的变量称为局部变量
局部变量的作用:临时存储函数内某个数据, 当函数执行结束后局部变量会销毁释放对应的内存
局部变量的使用范围: 只能在当前函数内使用,不能在函数外或者其它函数内使用
def show_info():
    # 局部变量
    name = "李四"
    # 在当前函数内使用这个局部变量
    print("姓名:", name)
    
show_info(


9.全局变量和修改全局变量
全局变量:在函数外定义的变量,称为全局变量
全局变量的作用:可以在不同函数之间共享全局变量的数据
全局变量的使用范围:可以在不同函数之间使用,相当于在当前的这个python文件中可以使用
 
 
# 定义全局变量
num = 10


def task1():
    print("task1函数内使用全局变量的数据为:", num)


def task2():
    print("task2函数内使用全局变量的数据为:", num)


task1()
task2()
print(num)

修改全局变量
#需求:在函数内修改全局变量
g_num = 100


def modify_value():
    # 声明要修改全局变量,这里不是再定义一个局部变量啦
    global g_num
    g_num = 200
    # 本意是要修改全局变量,但是这里其实是定义了一个局部变量,只不过局部变量的名字和全局变量的名字相同而已
    # g_num = 200
    print("在函数内修改全局变量,修改后全局变量的数据为:", g_num)


modify_value()
# 再次访问全局变量的时候,该数据应该是修改后的数据200
print("再次访问全局变量:", g_num)

# 总结:
# 在函数内修改全局变量需要使用global关键字
 
 


10.函数之间共享数据的操作
函数之间共享数据的操作
1. 使用全局变量
2. 通过函数的返回值
g_score = 100


def show_msg():
    print("show_msg 访问全局变量的数据为:", g_score)


def show_info():
    print("show_info 访问全局变量的数据为:", g_score)


show_msg()
show_info()


def return_data():
    msg = "ok"
    return msg


def show_data():
    # 获取返回值
    result = return_data()
    print("结果为:", result)


def info():
    # 获取返回值
    result = return_data()
    print("info结果为:", result)

show_data()
info()

 

 
11.函数返回多个值
return特点  :
# 1.当函数执行完return语句以后,表示函数执行结束,return后面的代码不会执行
# 2.return语句只能返回1次。

# return想要返回多个数据,需要结合容器类型使用,把多个要返回的数据放到容器类型里面,返回容器类型的数据即可。


def return_more_value():
    # return [1, 2]
    # return {"num1": 1, "num2:": 2}
    # return (1, 2)
    # 返回多个数据的简写方式
    return 1, 2 # 返回的是一个元组


result = return_more_value()
print(result, type(result))

# 总结:函数想要通过return返回多个数据,可以结合容器类型来完成。


12.缺省参数
缺省参数:在定义函数时,给形参进行赋值,那么该形参称为缺省参数
缺省参数的特点: 当调用函数时,给缺省参数设置值了,则使用设置的数据,否则使用默认值
缺省参数的注意点: 缺省参数后面可以在跟上缺省参数,不能再跟上普通的形参。
def sum_num(num1, num2=10, num3=30):
    value = num1 + num2
    return value


# result = sum_num(1, 2)
# print("结果为:", result)

result = sum_num(1)
print("结果为:", result)


13.调用函数的三种传参方式
调用函数时的参数传参方式
1. 按照位置参数的方式进行传参, 注意点:位置参数顺序一定要和函数定义时形参的顺序保持一致
2. 按照关键字参数的方式进行传参, 注意点:关键字的名字一定要和函数定义时形成的名字保持一致
3. 按照复合参数(前面使用位置参数,后面使用关键字参数)的方式进行传参
注意点: 一旦前面使用关键字参数,那么后面就不能再使用位置参数了,只能使用关键字参数
def show_info(name, age, sex):
    print("姓名:", name, "年龄:", age, "性别:", sex)


# 按照位置参数的方式进行传参 =========
# show_info("李四", 20, "男")
# 注意点:位置参数顺序一定要和函数定义时形参的顺序保持一致, 下面是错误写法
# show_info("李四", "男", 20)

# 按照关键字参数的方式进行传参 ==========
# show_info(name="王五", age=30, sex="男")
# 按照关键字参数的方式进行传参不强调关键字参数的顺序
# show_info(name="王五", sex="男", age=30)
# show_info(name="王五", sex="男", age1=30)

# 按照复合参数(前面使用位置参数,后面使用关键字参数)的方式进行传参 ======
# show_info("李六", 20, sex="男")
# 注意点:按照复合参数的方式进行传参是,一旦前面使用关键字参数,那么后面就不能再使用位置参数了,只能
# 使用关键字参数
show_info("张三", age=30, sex="")



14.不定长参数
不定长参数:在定义函数时,不确定接收参数的个数,此时可以使用不定长参数
不定长参数的表现形式
  1. *args: 表示在调用函数时,专门来负责接收不确定个数的位置参数的。
  2. **kwargs:表示在调用函数时,专门来负责接收不确定个数的关键字参数的。
# 定义一个带有不定长位置参数的函数
# 提示:可以修改args的名字,但一般不改
# def show_info(*args):
#     print(args, type(args))


# 当调用函数的时候,会把所有的位置参数打包到一个元组里面,然后把元组赋值给args,也就是说args是元组类
# show_info(1, 2)

# 定义一个带有不定长关键字参数的函数
# def show_info(**kwargs):
#     print("kwargs:", kwargs, type(kwargs))


# 当调用函数时,会把所有的关键字参数打包到一个字典里面,然后把字典赋值给kwargs,也就是说kwargs是字典
# show_info(a=1, b=2)

# 定义一个函数带有不定长位置参数和不定长关键字参数
def show_info(*args, **kwargs):
    print("args:", args, type(args))
    print("kwargs:", kwargs, type(kwargs))


# show_info(1, 2)
# show_info(c=1, d=2)
# show_info(1, 2, a="张三", b="李四")
show_info()


15.解包传参
def show_info(name, age, sex):
    print("name:", name, "age:", age, "sex:", sex)


my_tuple = ("李四", 20, "")
# # *my_tuple: 表示对元组进行解包传参,把元组中的每一个数据按照位置参数的方式进行传参
# show_info(*my_tuple)  # =》 show_info("李四", 20, "男")


my_dict = {"name": "王五", "age": 30, "sex": ""}

# **my_dict: 表示对字典进行解包传参,把字典中的每项数据按照关键字参数的方式进行传参
show_info(**my_dict) # => show_info(name="王五", age=30, sex="男")
 
 


16.缺省参数结合不定长参数
注意点:
1.当缺省参数结合不定长位置参数一起使用的时候,需要把缺省参数放到不定长位置参数(*args)的后面
2.当不定长关键字参数结合其它参数一起使用的时候
# 当缺省参数结合不定长位置参数一起使用的时候,需要把缺省参数放到不定长位置参数(*args)的后面
# def show_info(name, *args, age=18):
#     print("name:", name, "age:", age, "args:", args)
#
#
# # show_info("李四", 20, 1, 3, 4)
# show_info("李四", 1, 3, 4)
# show_info("李四", 1, 3, 4, age=20)


# 当不定长关键字参数结合其它参数一起使用的时候,那么不定长关键字参数(**kwargs)需要放到所有参数的最后面
def show_info(name, *args, age=18, **kwargs):
    print("name:", name, "age:", age, "args:", args, "kwargs:", kwargs)

# show_info("李四", 1, 3, 5, a=5, b=6)
# 注点意:当使用关键字进行传参的时候,先判断有没有对应的形参,如果有把数据给形参,否则给**kwargs参数
# show_info("李四", 1, 3, 5, a=5, b=6, age=30)


show_info("李四", 1, 3, 5, age=20, a=5, b=6)
 

17.拆包
拆包:使用不同变量保存容器类型中的每一个数据的操作,称为拆包
拆包的目的:获取容器类型中的每一个数据

my_list = ["A", "B", 3] # 利用拆包,使用三个变量分别保存列表中的每一个数据 value1, value2, value3 = my_list print(value1, value2, value3) my_dict = {"name": "吕布", "age": 30} # 对字典直接进行拆包,获取的key # data1, data2 = my_dict # print(data1, data2) data1, data2 = my_dict.values() print(data1, data2)

 


18.交换两个变量的值
num1 = 3
num2 = 5

print("num1:", num1, "num2:", num2)

# 通用写法,交换两个变量的值 =================
# temp = num1
# num1 = num2
# num2 = temp
#
# print("num1:", num1, "num2:", num2)

# 利用拆包,交换两个变量的值 =========================
# num1, num2 = num2, num1
# print("num1:", num1, "num2:", num2)

# # 1. 先把num2和num1组装到一个元组
# result = num2, num1
# print(result, type(result))
# # 2. 利用拆包,重新给num1和num2赋值
# num1, num2 = result
# print("num1:", num1, "num2:", num2)

# 先把num2,num1进行组包操作,然后再利用拆包,交换两个变量的值
num1, num2 = num2, num1
print("num1:", num1, "num2:", num2)
 
 

 


19.引用
引用:变量对数据内存地址的使用称为引用, 通俗理解变量使用了某个内存地址称为引用该数据的内存地址
提示:变量最终保存的是数据在内存中的一个地址,也就是说变量保存的是内存地址, 数据都是保存在内存里面
内存地址:就是数据在内存中的一个物理位置, 通过内存地址可以在内存中找到对应的数据。
# 严格来说,定义了一个变量,存储的是数据1在内存中的地址。
num1 = 1
# id函数是用来查看变量保存的内存地址
num1_id = id(num1)
print("num1:", num1, "num1保存的内存地址:", num1_id)

# 定义了一个变量,名字是num2, 保存的是num1存储的内存地址。也就是说这个两个变量引用的是同一个内存地址。
num2 = num1
num2_id = id(num2)
print("num2:", num2, "num2保存的内存地址:", num2_id)

# 重新给num1赋值, 修改了变量保存的引用
num1 = 10
num1_id = id(num1)
print("num1:", num1, "num1保存的内存地址:", num1_id)
print("num2:", num2, "num2保存的内存地址:", num2_id)

 

20.可变类型
可变类型:允许在原有内存空间的基础上修改数据,修改后数据的内存地址不变
可变类型有: 列表,字典,集合
name_list = ["西施", "貂蝉"]
print("修改前:", name_list, id(name_list))

# name_list.append("杨玉环")
del name_list[-1]
print("修改后:", name_list, id(name_list))

person_dict = {"name": "关羽", "age": 30}

print("修改前:", person_dict, id(person_dict))

person_dict["age"] = 40
print("修改后:", person_dict, id(person_dict))
 

21.不可变类型
不可变类型: 不允许在原有内存空间的基础上修改数据,修改后数据的内存地址会发生变化
不可变类型: 数字,字符串,元组,range
my_str = "abc"

print("修改前:", my_str, id(my_str))
# 错误写法
# my_str[-1] = 'f'
# print(my_str)
# 替换字符串后会返回一个新的字符串
# new_str = my_str.replace("c", "f")
# print("修改后:", new_str, id(new_str))
# print("修改后:", my_str, id(my_str))

# 通过重新赋值,来修改数据,相当于修改变量的引用
my_str = "abf"
print("修改后:", my_str, id(my_str))

my_num = 100
print("修改前:", my_num, id(my_num))
# 重新赋值,相当于修改变量的引用
my_num = 200
print("修改后:", my_num, id(my_num))

# 总结:对于不可变类型来时,修改数据只能重新赋值,相当于修改变量的引用。
 

22.+=操作的本质
+=操作的本质是要在原有内存空间的基础上修改数据,前提是该数据是可变类型
注意点:
  1.如果数据是可变类型,+=后 数据的内存地址不变
  2.如果数据是不可变类型,+=后 数据的内存地址会发生变化
def modify_value(params):
    print("修改前:", params, id(params))
    params += params
    print("修改后:", params, id(params))


# 可变类型的变量  =======
# my_list = [1, 2]
# print("my_list", my_list, id(my_list))
# modify_value(my_list) # params = my_list

# 不可变类型的变量
my_num = 10
print("my_num", my_num, id(my_num))
modify_value(my_num) # params = my_num

# 在python里面所有的赋值操作都是按照引用传递,就是按照内存地址传递的
 

23.函数使用的注意事项
1. return注意点
  1.1 当函数或者方法执行完return关键字以后,表示函数或者方法执行结束,return后面的代码不会执行
  1.2 return只能返回1次数据
  1.3 return关键字只能在函数或者方法内使用,不能单独使用

2. 函数名相同的注意点
  2.1 函数名相同,会把之前的函数进行覆盖

3. 变量作用域的注意点
  3.1 局部变量只能在当前函数内使用
  3.2 全局变量可以在不同函数或者函数外使用,相当于在当前的python文件中可以使用。


24函数结合return让多层循环终止
def show():

    for data in range(0, 11, 2):
        print("外层循环生成的数据为:", data)

        for value in range(1, 7, 2):
            print("内层循环生成的数据为:", value)
            if value == 3:
                # 当函数一旦执行return语句以后,则函数执行结束
                return


show()
 
 

 


25.global关键字的本质
global 关键字的本质:表示声明要修改全局变量的引用,其实说白了就是要修改全局变量保存的内存地址。
不管是可变类型还是不可变类型只要对全局变量进行重新赋值,那么都需要在函数内加上global
# g_list = []
#
#
# # 通过函数修改全局变量的数据
# def modify_value():
#     # 因为g_list是列表类型,它属于可变类型,修改数据后内存地址不变。
#     # 这里并没有对g_list变量的引用进行修改,所以不需要加上global
#     # g_list.append("李四")
# # 在函数里面对全局变量进行重新赋值操作,相当于修改了全局变量的引用,需要加上global # global g_list # g_list = ["李四"] # print("函数修改后全局变量的数据为:", g_list, id(g_list)) # # # print("修改前:", g_list, id(g_list)) # modify_value() # print("修改后:", g_list, id(g_list)) # 不可变类型全局变量的使用 ================== g_num = 10 def modify_value(): # 表示声明要修改全局变量的引用, global g_num g_num = 20 print("函数修改后全局变量的数据为:", g_num, id(g_num)) print("修改前:", g_num, id(g_num)) modify_value() print("修改后:", g_num, id(g_num))
 

26.递归函数
递归函数: 在一个函数内部再次调用函数本身,该定义的函数称为递归函数
注意点: 递归函数不能无限制的自己调用自己,必须要有结束递归调用条件
递归函数的形参条件:
  1. 在函数内部调用函数本身
  2. 必须要有结束递归调用条件
# 递归函数的定义
def show(count):
    print("哈哈,今天学习递归函数啦...")
    # count == 1 就是结束递归调用的条件,当满足这个条件是不需要再自己调用函数本身啦
    if count == 1:
        print("递归结束:over")
    else:
        # 在函数内部,再次调用函数本身
        show(count - 1)


# 调用show函数
show(3)

 


27.匿名函数
匿名函数:使用lambda关键字定义的函数,称为匿名函数,有的地方说没有名字函数就是匿名函数

学习匿名函数的目的:简化之前普通函数的功能代码
匿名函数的特点:
1.匿名函数只能写一行代码
2.匿名函数的返回值不需要加上return
3.匿名函数也是函数,在调用匿名函数的时候也需要加上()

匿名函数的语法格式:
lambda 形参1, 参数2,...: 返回值或者调用其它函数

# 使用def定义一个函数,实现求两个数字的和
def sum_num(n1, n2):
    return n1 + n2


# result = sum_num(1, 2)
# print(result)


# ============== 使用匿名函数对以上函数的功能代码进行简化 ===========
# 为了后续使用匿名函数更加方便,一般会使用变量来保存匿名函数
new_func = lambda x, y: x + y

print("new_fun变量的类型:", type(new_func))
print("sum_num函数的类型:", type(sum_num))
result = new_func(1, 2)
print("结果为:", result)

# 定义一个无参数无返回值的匿名函数
my_func = lambda: print("人生苦短,我用python!")
my_func()

 













 

你可能感兴趣的:(函数)