Python函数知识点总结

目标

函数的快速体验
函数的基本使用
函数的参数
函数的返回值
函数的嵌套调用
在模块中定义函数
  1. 函数的快速体验
    1.1 快速体验

    所谓函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
    函数的使用包含两个步骤:
    定义函数 —— 封装 独立的功能
    调用函数 —— 享受 封装 的成果
    函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的 重用

演练步骤

新建 04_函数 项目
复制之前完成的 乘法表 文件
修改文件,增加函数定义 multiple_table():
新建另外一个文件,使用 import 导入并且调用函数
  1. 函数基本使用
    2.1 函数的定义

定义函数的格式如下:

def 函数名():

函数封装的代码
……

def 是英文 define 的缩写
函数名称 应该能够表达 函数封装代码 的功能,方便后续的调用
函数名称 的命名应该 符合 标识符的命名规则
    可以由 字母、下划线 和 数字 组成
    不能以数字开头
    不能与关键字重名

2.2 函数调用

调用函数很简单的,通过 函数名() 即可完成对函数的调用
2.3 第一个函数演练

需求

  1. 编写一个打招呼 say_hello 的函数,封装三行打招呼的代码
  2. 在函数下方调用打招呼的代码
name = "小明"


#解释器知道这里定义了一个函数
def say_hello():
    print("hello 1")
    print("hello 2")
    print("hello 3")

print(name)
#只有在调用函数时,之前定义的函数才会被执行
#函数执行完成之后,会重新回到之前的程序中,继续执行后续的代码
say_hello()

print(name)

用 单步执行 F8 和 F7 观察以下代码的执行过程

定义好函数之后,只表示这个函数封装了一段代码而已
如果不主动调用函数,函数是不会主动执行的

思考

能否将 函数调用 放在 函数定义 的上方?
    不能!
    因为在 使用函数名 调用函数之前,必须要保证 Python 已经知道函数的存在
    否则控制台会提示 NameError: name 'say_hello' is not defined (名称错误:say_hello 这个名字没有被定义)

2.4 PyCharm 的调试工具

F8 Step Over 可以单步执行代码,会把函数调用看作是一行代码直接执行
F7 Step Into 可以单步执行代码,如果是函数,会进入函数内部

2.5 函数的文档注释

在开发中,如果希望给函数添加注释,应该在 定义函数 的下方,使用 连续的三对引号
在 连续的三对引号 之间编写对函数的说明文字
在 函数调用 位置,使用快捷键 CTRL + Q 可以查看函数的说明信息

注意:因为 函数体相对比较独立,函数定义的上方,应该和其他代码(包括注释)保留 两个空行
  1. 函数的参数

演练需求

开发一个 sum_2_num 的函数
函数能够实现 两个数字的求和 功能

演练代码如下:

def sum_2_num():

    num1 = 10
    num2 = 20
    result = num1 + num2

    print("%d + %d = %d" % (num1, num2, result))

	sum_2_num()

思考一下存在什么问题

函数只能处理 固定数值 的相加

如何解决?

如果能够把需要计算的数字,在调用函数时,传递到函数内部就好了!

3.1 函数参数的使用

在函数名的后面的小括号内部填写 参数
多个参数之间使用 , 分隔

def sum_2_num(num1, num2):

    result = num1 + num2
    
    print("%d + %d = %d" % (num1, num2, result))

	sum_2_num(50, 20)

3.2 参数的作用

函数,把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
函数的参数,增加函数的 通用性,针对 相同的数据处理逻辑,能够 适应更多的数据
在函数 内部,把参数当做 变量 使用,进行需要的数据处理
函数调用时,按照函数定义的参数顺序,把 希望在函数内部处理的数据,通过参数 传递

3.3 形参和实参

形参:定义 函数时,小括号中的参数,是用来接收参数用的,在函数内部 作为变量使用
实参:调用 函数时,小括号中的参数,是用来把数据传递到 函数内部 用的

函数的返回值

在程序开发中,有时候,会希望 一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
返回值 是函数 完成工作后,最后 给调用者的 一个结果
在函数中使用 return 关键字可以返回结果
调用函数一方,可以 使用变量 来 接收 函数的返回结果

注意:return 表示返回,后续的代码都不会被执行

def sum_2_num(num1, num2):
    """对两个数字的求和"""

    return num1 + num2

	#调用函数,并使用 result 变量接收计算结果
	result = sum_2_num(10, 20)
	
	print("计算结果是 %d" % result)

函数的嵌套调用

一个函数里面 又调用 了 另外一个函数,这就是 函数嵌套调用
如果函数 test2 中,调用了另外一个函数 test1
    那么执行到调用 test1 函数时,会先把函数 test1 中的任务都执行完
    才会回到 test2 中调用函数 test1 的位置,继续执行后续的代码

def test1():

    print("*" * 50)
    print("test 1")
    print("*" * 50)


def test2():

    print("-" * 50)
    print("test 2")
    
    test1()
    
    print("-" * 50)

test2()

函数嵌套的演练 —— 打印分隔线

体会一下工作中 需求是多变 的

需求 1
	
	    定义一个 print_line 函数能够打印 * 组成的 一条分隔线
	
	def print_line(char):

	    print("*" * 50)

需求 2

    定义一个函数能够打印 由任意字符组成 的分隔线

	def print_line(char):
	
	    print(char * 50)
    

需求 3

    定义一个函数能够打印 任意重复次数 的分隔线

	def print_line(char, times):
	
	    print(char * times)

需求 4

    定义一个函数能够打印 5 行 的分隔线,分隔线要求符合需求 3

    提示:工作中针对需求的变化,应该冷静思考,不要轻易修改之前已经完成的,能够正常执行的函数!
	
	def print_line(char, times):
	
	    print(char * times)


def print_lines(char, times):

    row = 0
    
    while row < 5:
        print_line(char, times)

        row += 1
  1. 使用模块中的函数

    模块是 Python 程序架构的一个核心概念

    模块 就好比是 工具包,要想使用这个工具包中的工具,就需要 导入 import 这个模块
    每一个以扩展名 py 结尾的 Python 源代码文件都是一个 模块
    在模块中定义的 全局变量 、 函数 都是模块能够提供给外界直接使用的工具

6.1 第一个模块体验

步骤

新建 hm_10_分隔线模块.py
    复制 hm_09_打印多条分隔线.py 中的内容,最后一行 print 代码除外
    增加一个字符串变量

name = "程序员"

    新建 hm_10_体验模块.py 文件,并且编写以下代码:

import hm_10_分隔线模块

hm_10_分隔线模块.print_line("-", 80)
print(hm_10_分隔线模块.name)

体验小结

可以 在一个 Python 文件 中 定义 变量 或者 函数
然后在 另外一个文件中 使用 import 导入这个模块
导入之后,就可以使用 模块名.变量 / 模块名.函数 的方式,使用这个模块中定义的变量或者函数

模块可以让 曾经编写过的代码 方便的被 复用!

6.2 模块名也是一个标识符

标示符可以由 字母、下划线 和 数字 组成
不能以数字开头
不能与关键字重名

注意:如果在给 Python 文件起名时,以数字开头 是无法在 PyCharm 中通过导入这个模块的

6.3 Pyc 文件(了解)

C 是 compiled 编译过 的意思

操作步骤

浏览程序目录会发现一个 __pycache__ 的目录
目录下会有一个 hm_10_分隔线模块.cpython-35.pyc 文件,cpython-35 表示 Python 解释器的版本
这个 pyc 文件是由 Python 解释器将 模块的源码 转换为 字节码
    Python 这样保存 字节码 是作为一种启动 速度的优化

字节码

Python 在解释源程序时是分成两个步骤的
    首先处理源代码,编译 生成一个二进制 字节码
    再对 字节码 进行处理,才会生成 CPU 能够识别的 机器码

有了模块的字节码文件之后,下一次运行程序时,如果在 上次保存字节码之后 没有修改过源代码,Python 将会加载 .pyc 文件并跳过编译这个步骤

当 Python 重编译时,它会自动检查源文件和字节码文件的时间戳

如果你又修改了源代码,下次程序运行时,字节码将自动重新创建

提示:有关模块以及模块的其他导入方式,后续课程还会逐渐展开!

模块是 Python 程序架构的一个核心概念

一、函数的基本使用

①函数必须先定义,才能被调用
def Fun1():
    print("先定义才能被调用")
Fun1()

 ②Python中的main()函数为普通函数,由于约定俗成的习惯,用main()表示函数入口.

③断点:程序加载后,程序停止在断点,等待进行下一个操作。

 ④检查代码是否符合PEP8标准,使得代码规范。

 ⑤使用函数的好处:
 减低代码量
 可以降低维护成本
 容易阅读
 ⑥函数的文档    help(函数名) 在函数里查看文档说明
文档不打印,文档和注释不一样。可以查阅文档,(文档要缩进)
 文档必须在创建函数的时候就写。
 用“”“”“”
 ⑦在Python函数中,都是有返回值的。
 ⑧一般在函数中不要使用全局变量。 这样代码的可读性变差,安全性降低。

二、函数参数使用
形参和实参

def parameter(name):
    print(name)         #其中name为形参,“刘海涛”为实参
parameter("刘海涛")

(一)return的用法

def Fun1(x, y):
    return x + y
 ②这句话没有执行,上面的return已经结束函数执行
    print("看看执行了没有")
result = Fun1(5,6)
 ①返回一个数据,给函数调用的地方
print(result)
 ③如果return后没有数据,则默认返回,返回值为none

(二)位置参数 位置参数一般配合*arg使用

 位置参数中,参数的顺序必须对应,且不能缺少参数
def Fun(a, b, c):
    return a + b + c
print(Fun(4, 5, 6))

(三)关键字参数

①如果不确定参数顺序,可以通过关键字函数传出来
 ③最后一个可以使用关键字参数
def Fun(a, b, c):
    return a * b * c
print(Fun(1, 2, c=3))
 ②关键字参数后面参数都是关键字参数
def Fun(a, b, c):
    return a * b * c
print(Fun(1, b=2, 3))  ####报错

(四)默认参数

①在函数定义的时候就给了参数值,并且一般都写在位置参数后面
def Fun(a, b, c=1):
    return a + b + c
 ②如果调用时没有指定默认参数的值,则使用默认参数
print(Fun(1,2))         #结果为4
 ③如果调用时指定了默认参数的值,则覆盖默认参数
print(Fun(1, 2, 5))     #结果为8
 ④如果是默认参数,则用默认参数,覆盖原有的参数
print(Fun(1, 2, c=10))  #结果为13

(五)默认参数延伸
默认参数不能使用可变数据类型(list,dict)

参数全部为默认参数时,不需要再调用参数。
def Fun(list1 = []):
    list1.append(10)
    return list1
print(Fun())      # [10]
print(Fun())      # [10, 10]
print(Fun())      # [10, 10, 10]

 如果要使用列表,该怎么办?
def Fun():          # 把列表放到函数体内
    list1 = []
    list1.append(10)
    return list1
print(Fun())
print(Fun())
print(Fun())

(六)可变参数:不确定参数个数

 1、*args 收集所有的可变参数为元祖
def Fun(*args):
    for i in args:
        i += i
        return i
result = Fun(1, 2, 3)
print(result)
 2、**kwargs 收集所有关键字参数作为字典
def Fun(**args):
    k ,v = args.items()
    return k, v
print(Fun(a=1, b=2))

(七)命名关键字参数
控制命名关键字的个数(Python3新增)*号后的参数都必须为关键字参数

def person_info(name, age, *, city, job):
#*号后的参数都必须为关键字参数
    print(name)
    print(city)
person_info("刘海涛", 15, city="上海", job="programmer")

三、函数返回值(返回一个值或多个值)
(一)返回一个值
pass的用法

def calc_func(num1, num2, num3):
 用pass表示什么也不做,同时标记代码没有错误
    pass

编写简单计算机

def calc_func(num1, num2, num3):
    if num3 == "+":
        return num1 + num2
    elif num3 == "-":
        return num1 + num2
    elif num3 == "*":
        return num1 * num2
    elif num3 == "/":
        return num1 / num2
    else:
        print("输入不正确")
print(calc_func(1, 2, "+"))

(一)返回多个值

def square_func(num1, num2):
return返回了多个数据,则先进行打包(一个元祖),再返回
    return num1 ** 2, num2 ** 2
print(square_func(10,20))
 如何拆包?
x, y = square_func(10,20)
print(x,y)
 注意:字典运用拆包时,拆出来的是 键
d1, d2, d3 = {"name":"python", "age":27, "id":100}
print(d1, d2, d3)
四、全局变量和局部变量
①函数内部使用变量,不能在外部访问
def Func():
    age = 1
print(age)      #这么写是错的,不能被访问

 ②全局变量在模块内定义,可以在整个模块内使用,函数内部可以访问全局变量
age = 1
def Fun():
    print(age)
Fun()

 ③什么时候用global,先声明再使用全局变量,并可随意改全局变量
   global可以声明全局变量,并可以修改全局变量和局部变量的指向。
   如果只是获得全局变量,有没有global都一样
   如果要修改全局变量的值,就必须使用
   如果是可变数据类型,不管有没有修改,都不要global
age = 10
def Func():
    global age
    age = 20
    print(age)
Func()
print(age)  # 全局变量的age也更改了

五、命名空间

(一)命名空间(作用域)为了防止多个变量冲突,而引入一组对变量名作用范围分组机制。
1、局部命名空间:函数内的命名空间是局部的
2、全局的命名空间:模块类的命名为全局的
3、内置命名空间:内置函数,异常处理等
4、一个Python表达式,可以访问局部命名空间和全局命名空间,如果变量重名,则局部命名空间覆盖全局命名空间。(从内到外,强龙不压地头蛇)
age = 10
def func():
    age = 5
    return age
print(func())

(二)命名空间的访问
1、locals() 包含了所有局部变量的命名空间全部是字典。

def Func():
    a = 10
 把这个局部的变量 编程字典
    return locals()
print(Func())

2、globals() 包含了所有全局变量的命名空间全部是字典。

golbals() 在函数体内也能访问全局变量。
b = 20
def Func():
    a = 10
    # 访问的不是10,而是在函数里访问的外部的20
    return globals()
print(Func())
 把这个全局变量变成字典
print(globals())

(三)命名空间查找顺序(LEGB规则)Python2.2之前不支持
L – Local 局部命名空间
E – Enclosing (嵌套函数)外部
G – Global 全球的,全局命名空间
B – BIF 内置命名空间 内置函数
(四)命名空间的生命周期

1、局部命名空间的生命周期:
   当函数结束时(return,正常执行结果,抛出异常),
   该命名空间下的变量全部销毁。
2、全局命名空间的生命周期:
   从模块加载的代码执行开始,到程序结束后,是全局命名
   空间的存货时间。
3、内置命名空间:从Python的解释器启动开始,到程序执行结束

五、匿名函数(lambda)

(一)lambda的基本定义
①lambda表达式是单一的,没有语句块
 ②lambda表达式可以有参数,也可以无参数。
③lambda表达式默认值带返回值
 ④lambda可以有函数名

 无参   另一种表达形式  print(lambda:10())
f = lambda: 10
print(f())

有参,冒号左边是参数,右边是返回值(返回值只能为表达式或者if)
f = lambda x, y: x + y
print(f(1, 2))
print((lambda x, y: x if x > y else y)(2, 3))
(二)lambda表达式支持默认参数、元祖类型多变参数,字典类型多变参数,表达式作为参数传递。
Python对匿名函数支持有限,只有一些简单的情况下可以使用匿名函数。
 ①默认参数
print((lambda a, b, c=5 : a + b + c)(1, 2))

②元祖数据多变参数,返回元组类型。
print((lambda *args: args)(1, 2, 3, 4))

③字典数据类型多变参数,返回字典类型,参数为关键字参数
print((lambda **kwargs: kwargs)(a=1, b=2, c=3))

 ④lambda表达式为参数传递
def Func(a, b, f):
    return f(a, b)
print(Func(1, 2, lambda x, y: x + y))

 ⑤filter()过滤器   会把非True筛出,即0
 使用filter()和lambda表达式快速求出100以内所有3的倍数
a = list(filter(lambda x : x%3 == 0 ,range(101)))
print(a)     #filter()返回list和reversed一样 或者tuple

⑥map() 映射   zip()
b = list(map(lambda x,y : [x,y],[1,2,3,4,5],[6,7,8,9]))
print(b)    是列表类型的列表
c = list(zip([1,2,3],[4,5,6])) #zip()出来的是元祖类型的列表
print(c)

六、递归

1、递归函数调自己拷贝到内存中
2、递归函数会一直调用自身的拷贝,同时返回值会返回给调用他的拷贝函数
3、使用不当让系统崩溃
4、Python3语序最大递归深度在990到1000之间
5、递归函数可以变相理解为是一种"循环体"

七、函数嵌套(练一练)
1、内嵌函数,只能在外部函数中使用,不能再全局变量中使用
再嵌套函数中,如果想用内部函数修改外部函数的变量用 nonlocal 关键字

def Fun1():
    x = 5
    def Fun2():
        nonlocal x
        x *= x          #外部函数中的5被修改成25
        return x
    return Fun2()
print(Fun1())

2、# 如何访问funInt呢?

def funOut():
    def funInt():
        print("苹果,你成功访问到我了")
    return funInt
#由于返回的是funInt,所以要访问funInt()必须用
funOut()()

3、闭包,(closer)如果在一个内部函数里,在外部作用于的变量内部函数就是一个闭包

def funX(x):
    def funY(y):
        return x * y
    return funY
print(funX(5)(8))

目标

函数参数和返回值的作用
函数的返回值 进阶
函数的参数 进阶
递归函数

函数参数和返回值的作用

函数根据 有没有参数 以及 有没有返回值,可以 相互组合,一共有 4 种 组合形式

无参数,无返回值
无参数,有返回值
有参数,无返回值
有参数,有返回值

001_函数参数和返回值

定义函数时,是否接收参数,或者是否返回结果,是根据 实际的功能需求 来决定的!

如果函数 内部处理的数据不确定,就可以将外界的数据以参数传递到函数内部
如果希望一个函数 执行完成后,向外界汇报执行结果,就可以增加函数的返回值

1.1 无参数,无返回值

此类函数,不接收参数,也没有返回值,应用场景如下:

只是单纯地做一件事情,例如 显示菜单
在函数内部 针对全局变量进行操作,例如:新建名片,最终结果 记录在全局变量 中

注意:

如果全局变量的数据类型是一个 可变类型,在函数内部可以使用 方法 修改全局变量的内容 —— 变量的引用不会改变
在函数内部,使用赋值语句 才会 修改变量的引用

1.2 无参数,有返回值

此类函数,不接收参数,但是有返回值,应用场景如下:

采集数据,例如 温度计,返回结果就是当前的温度,而不需要传递任何的参数

1.3 有参数,无返回值

此类函数,接收参数,没有返回值,应用场景如下:

函数内部的代码保持不变,针对 不同的参数 处理 不同的数据
例如 名片管理系统 针对 找到的名片 做 修改、删除 操作

1.4 有参数,有返回值

此类函数,接收参数,同时有返回值,应用场景如下:

函数内部的代码保持不变,针对 不同的参数 处理 不同的数据,并且 返回期望的处理结果
例如 名片管理系统 使用 字典默认值 和 提示信息 提示用户输入内容
    如果输入,返回输入内容
    如果没有输入,返回字典默认值

02. 函数的返回值 进阶

在程序开发中,有时候,会希望 一个函数执行结束后,告诉调用者一个结果,以便调用者针对具体的结果做后续的处理
返回值 是函数 完成工作后,最后 给调用者的 一个结果
在函数中使用 return 关键字可以返回结果
调用函数一方,可以 使用变量 来 接收 函数的返回结果

问题:一个函数执行后能否返回多个结果?

示例 —— 温度和湿度测量

假设要开发一个函数能够同时返回当前的温度和湿度
先完成返回温度的功能如下:

def measure():
    """返回当前的温度"""
    
    print("开始测量...")
    temp = 39
    print("测量结束...")
    
    return temp

result = measure()
print(result)

在利用 元组 在返回温度的同时,也能够返回 湿度
改造如下:

def measure():
    """返回当前的温度"""

    print("开始测量...")
    temp = 39
    wetness = 10
    print("测量结束...")

    return (temp, wetness)

    提示:如果一个函数返回的是元组,括号可以省略

技巧

在 Python 中,可以 将一个元组 使用 赋值语句 同时赋值给 多个变量
注意:变量的数量需要和元组中的元素数量保持一致

result = temp, wetness = measure()

面试题 —— 交换两个数字

题目要求

有两个整数变量 a = 6, b = 100
不使用其他变量,交换两个变量的值
解法 1 —— 使用其他变量	
#解法 1 - 使用临时变量
c = b
b = a
a = c
解法 2 —— 不使用临时变量
#解法 2 - 不使用临时变量
a = a + b
b = a - b
a = a - b	
解法 3 —— Python 专有,利用元组
a, b = b, a

函数的参数 进阶
3.1. 不可变和可变的参数

问题 1:在函数内部,针对参数使用 赋值语句,会不会影响调用函数时传递的 实参变量? —— 不会!

无论传递的参数是 可变 还是 不可变
    只要 针对参数 使用 赋值语句,会在 函数内部 修改 局部变量的引用,不会影响到 外部变量的引用
def demo(num, num_list):

    print("函数内部")

    # 赋值语句
    num = 200
    num_list = [1, 2, 3]

    print(num)
    print(num_list)

    print("函数代码完成")

gl_num = 99
gl_list = [4, 5, 6]
demo(gl_num, gl_list)
print(gl_num)
print(gl_list)
   
问题 2:如果传递的参数是 可变类型,在函数内部,使用 方法 修改了数据的内容,同样会影响到外部的数据

def mutable(num_list):

    # num_list = [1, 2, 3]
    num_list.extend([1, 2, 3])
    
    print(num_list)

gl_list = [6, 7, 8]
mutable(gl_list)
print(gl_list)

面试题 —— +=

在 python 中,列表变量调用 += 本质上是在执行列表变量的 extend 方法,不会修改变量的引用

def demo(num, num_list):

    print("函数内部代码")

    # num = num + num
    num += num
    # num_list.extend(num_list) 由于是调用方法,所以不会修改变量的引用
    # 函数执行结束后,外部数据同样会发生变化
    num_list += num_list

    print(num)
    print(num_list)
    print("函数代码完成")


gl_num = 9
gl_list = [1, 2, 3]
demo(gl_num, gl_list)
print(gl_num)
print(gl_list)

3.2 缺省参数

定义函数时,可以给 某个参数 指定一个默认值,具有默认值的参数就叫做 缺省参数
调用函数时,如果没有传入 缺省参数 的值,则在函数内部使用定义函数时指定的 参数默认值
函数的缺省参数,将常见的值设置为参数的缺省值,从而 简化函数的调用
例如:对列表排序的方法

gl_num_list = [6, 3, 9]

#默认就是升序排序,因为这种应用需求更多
gl_num_list.sort()
print(gl_num_list)

#只有当需要降序排序时,才需要传递 reverse 参数
gl_num_list.sort(reverse=True)
print(gl_num_list)

指定函数的缺省参数

在参数后使用赋值语句,可以指定参数的缺省值

def print_info(name, gender=True):

    gender_text = "男生"
if not gender:
    gender_text = "女生"

print("%s 是 %s" % (name, gender_text))

提示

缺省参数,需要使用 最常见的值 作为默认值!
如果一个参数的值 不能确定,则不应该设置默认值,具体的数值在调用函数时,由外界传递!

缺省参数的注意事项

  1. 缺省参数的定义位置

    必须保证 带有默认值的缺省参数 在参数列表末尾
    所以,以下定义是错误的!

    def print_info(name, gender=True, title):

  2. 调用带有多个缺省参数的函数

    在 调用函数时,如果有 多个缺省参数,需要指定参数名,这样解释器才能够知道参数的对应关系!

     def print_info(name, title="", gender=True):
     """
    
         :param title: 职位
         :param name: 班上同学的姓名
         :param gender: True 男生 False 女生
         """
     
         gender_text = "男生"
     
         if not gender:
             gender_text = "女生"
     
         print("%s%s 是 %s" % (title, name, gender_text))
    

#提示:在指定缺省参数的默认值时,应该使用最常见的值作为默认值!
print_info(“小明”)
print_info(“老王”, title=“班长”)
print_info(“小美”, gender=False)

3.3 多值参数(知道)
定义支持多值参数的函数

有时可能需要 一个函数 能够处理的参数 个数 是不确定的,这个时候,就可以使用 多值参数
python 中有 两种 多值参数:
    参数名前增加 一个 * 可以接收 元组
    参数名前增加 两个 * 可以接收 字典

一般在给多值参数命名时,习惯使用以下两个名字
    *args —— 存放 元组 参数,前面有一个 *
    **kwargs —— 存放 字典 参数,前面有两个 *

args 是 arguments 的缩写,有变量的含义

kw 是 keyword 的缩写,kwargs 可以记忆 键值对参数

def demo(num, *args, **kwargs):

    print(num)
    print(args)
    print(kwargs)


demo(1, 2, 3, 4, 5, name="小明", age=18, gender=True)

提示:多值参数 的应用会经常出现在网络上一些大牛开发的框架中,知道多值参数,有利于我们能够读懂大牛的代码

多值参数案例 —— 计算任意多个数字的和

需求

定义一个函数 sum_numbers,可以接收的 任意多个整数
功能要求:将传递的 所有数字累加 并且返回累加结果

def sum_numbers(*args):

    num = 0
# 遍历 args 元组顺序求和
for n in args:
    num += n

return num

print(sum_numbers(1, 2, 3))

元组和字典的拆包(知道)

在调用带有多值参数的函数时,如果希望:
    将一个 元组变量,直接传递给 args
    将一个 字典变量,直接传递给 kwargs
就可以使用 拆包,简化参数的传递,拆包 的方式是:
    在 元组变量前,增加 一个 *
    在 字典变量前,增加 两个 *

def demo(*args, **kwargs):

    print(args)
    print(kwargs)

#需要将一个元组变量/字典变量传递给函数对应的参数

gl_nums = (1, 2, 3)
gl_xiaoming = {"name": "小明", "age": 18}

#会把 num_tuple 和 xiaoming 作为元组传递个 args
#demo(gl_nums, gl_xiaoming)
demo(*gl_nums, **gl_xiaoming)
  1. 函数的递归

    函数调用自身的 编程技巧 称为递归

4.1 递归函数的特点

特点

一个函数 内部 调用自己
    函数内部可以调用其他函数,当然在函数内部也可以调用自己

代码特点

函数内部的 代码 是相同的,只是针对 参数 不同,处理的结果不同
当 参数满足一个条件 时,函数不再执行
    这个非常重要,通常被称为递归的出口,否则 会出现死循环!

示例代码

def sum_numbers(num):

    print(num)
    
    # 递归的出口很重要,否则会出现死循环
    if num == 1:
        return

    sum_numbers(num - 1)
    
	sum_numbers(3)

002_递归调用示意图I
4.2 递归案例 —— 计算数字累加

需求

定义一个函数 sum_numbers
能够接收一个 num 的整数参数
计算 1 + 2 + ... num 的结果

def sum_numbers(num):

    if num == 1:
        return 1
    
    # 假设 sum_numbers 能够完成 num - 1 的累加
    temp = sum_numbers(num - 1)

    # 函数内部的核心算法就是 两个数字的相加
    return num + temp

print(sum_numbers(2))

002_递归调用示意图

提示:递归是一个 编程技巧,初次接触递归会感觉有些吃力!在处理 不确定的循环条件时,格外的有用,例如:遍历整个文件目录的结构
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值