lena萌宝宝

导航

python视频学习笔记8(函数返回值和参数进阶)

如果函数内部有return,并且return后面跟有一个值,就是函数有返回值。可以是变量也可以是字符

如果函数内部有return,后面没有值,表示满足这个函数条件后,函数执行提前结束(后面的不执行)

 ## 目标

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

拆包

## 01. 函数参数和返回值的作用

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

1. 无参数,无返回值
2. 无参数,有返回值
3. 有参数,无返回值
4. 有参数,有返回值

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

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

### 1.1 无参数,无返回值

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

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

> 注意:

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

------------------------------------

def my_print():

      print(''nihao')

my_print()

------------------------------------

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

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

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

--------------------------------

def my_pi():

   return 3.1415926  #也可以直接返回一个字符串

    pi = my_pi()

print(pi)

----------------------------------------

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

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

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

---------------------------

def print_info(name):

     print(name)

print_info("lili")

---------------------------

### 1.4 有参数,有返回值

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

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

------------------------------------

def my_func(a,b):

   ret = a -b

  return ret

result = my_func(5,3)

------------------------------

## 02. 函数的返回值 

-----------------------------------------------------

def addnum(a,b) 

    ret = a + b  #定义一个变量来记录2个值的求和

return ret  #把函数执行结果返回

num= addnum(10,11) #此时来执行addnum这个函数,10和11带入运行上述函数后,收到了返回值;使用一个变量num来记录return的返回值,如果不用可以不定义num,直接执行

print(num)

---------------------------------------------------------------------------------------



2.1 多个return,函数中return后面无结果表示结束掉
--------------------------------------
# 定义一个函数 当执行函数的时候 传入一个分数 可以返回一个字符串 (优 良 中 差)

# 包含多个return
def my_func(score):
# 对分数进行判断
if score >= 90:
return "优"
elif score >= 80:
return "良"
elif score >= 60:
return "中"
elif score >= 0:
return "差"
# 他不会执行 因为在第11行已经执行了return
print("测试")
ret = my_func(89)
print(ret)

def my_func1():
print("开始")
# 只要函数中执行了return 提前结束函数的执行 而且return后面的代码将不再执行(后面的开始1 20 结束都不会执行)
return "3.14"
print("开始1")
return 20
print("结束")

ret = my_func1()
print(ret)
print("测试")

"""
开始
3.14
测试
"""

-----------------------------------------------
# 提出需求 如果调用函数的人 传入的分数小于0 那么就人为传入的分数错误 告知函数的调用者

# 01-作为函数的返回值
# 02-执行的函数提前结束 (为了提高性能考虑)
def my_func(score):
if score < 0:
print("您传入的分数有误!!!")
# 如果小于0,则函数的执行提前结束
return
print("测试")
# 对分数进行判断
if score >= 90:
return "优"
elif score >= 80:
return "良"
elif score >= 60:
return "中"
elif score >= 0:
return "差"
# 只要小于0,则这一段他不会执行 因为在第11行已经执行了return
print("测试")

my_func(-10)
-----------------------------------------------
2.2  一个函数返回多个数据(返回出列表,元组,字典)
-----------------------------------------
# 需求 传入一个人名字 和年龄
# 例如 小明 22
# 通过调用函数后 得到两个字符串 姓名:小明 年龄:22

# 列表
# def deal_name_age(name, age):
# # 处理后 姓名:小明 年龄:22
# new_name = "姓名:%s" % name
# new_age = "年龄:%d" % age
# return [new_name, new_age]

# ret = deal_name_age("小明", 22)
# print(ret[0])
# print(ret[1])

# 字典
# def deal_name_age(name, age):
# # 处理后 姓名:小明 年龄:22
# new_name = "姓名:%s" % name
# new_age = "年龄:%d" % age
# return {"name":new_name, "age":new_age}
#
# my_dict = deal_name_age("小明", 22)
# print(my_dict["name"])
# print(my_dict["age"])


# 元组
def deal_name_age(name, age):
# 处理后 姓名:小明 年龄:22
new_name = "姓名:%s" % name
new_age = "年龄:%d" % age
return new_name, new_age # 如果在函数内部 使用return 返回值1 返回值2,... 默认就是元组类型 不需要写小括号
#
my_tuple = deal_name_age("小明", 22)
print(type(my_tuple))
print(my_tuple[0])
print(my_tuple[1])

## 03. 函数的参数 

### 3.1. 不可变和可变的参数

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

----------------------------------------------------------------------------------

下面的例子当中num是个数字,之前说过数字是不可变类型。

第一步glnum标签被贴到99上

第二步开始执行demo,将变量glnum=99以参数的形式传递到函数中,那么num也被贴到99上

第三步开始将num重新贴到100上

结果num=100 glnum=99

-----------------------------------------------------------------------------------------

下面弄个可变类型参数

----------------------------------------------------------------------

demo中增加可变类型参数,列表/字典,numlist

定义全局列表,设置初始值456,并将列表当成实参传递到函数f内部

第一步"gllist应用列表456

第二步 开始执行demo,把gllist引用以参数的形式传递到函数内部,函数内部有numlist来接受,意味着函数内部建立了一个局部变量,并贴在了456上

第三步 函数内部内存中分配小格子记录123,并将numlist从456撕下来贴到123

结果gllist=456  numlist=123

`-------------------------------------------------------------------------------

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

 

> 问题 2:如果传递的参数是 **可变类型**,在函数内部使用 **方法** 修改了数据的内容,**同样会影响到外部的数据**

调用append方法不会修改列表的引用,只是在列表末尾追加了数字9

 

#### 面试题 —— `+=`,先相加后赋值

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

``

3.2函数传入关键字参数
------------------------

#定义一个函数
# python是一个弱类型
def my_print(name, age, no):
print("我的名字:%s" % name)
print("我的年龄:%d" % age)
print("学号:%s" % no)

# 调用-> 位置参数
# my_print("小明", 20)


# 关键字参数
# 调用函数的时候使用的是函数的形参名
# my_print(age=22, name="老王")
# my_print(name="老王", age=22)

# 调用函数的时候 使用了位置和关键字参数混合
# 如果混合使用 需要叫位置参数在前 关键字参数再后
# 如果某个参数使用了关键字参数 后面的都需要使用关键字参数
my_print("小明", age=20, no="007")
--------

3.3 函数参数传入缺省参数: 给形参设置了一个默认值
def my_print(name, age=20, no="001") 里面赋值了就是缺省参数
----------------------------
# # 定义一个函数 名字 学号 年龄
# def my_print(name, no, age):
# print("名字:%s" % name)
# print("学号:%s" % no)
# print("年龄:%d" % age)
# print("="*30)
#
#
# # 小明 001 20
# # 小红 002 20
# # 小张 003 20
# my_print("小明", "001", 20)
# my_print("小红", "002", 20)
# my_print("小张", "003", 20)


# 定义一个有缺省参数的函数
# 缺省参数: 给形参设置了一个默认值
# 定义一个函数 名字 学号 年龄
# def my_print(name, no, age=20):
#
# print("名字:%s" % name)
# print("学号:%s" % no)
# print("年龄:%d" % age)
# print("="*30)


# 小明 001 20
# 小红 002 20
# 小张 003 20
# 在调用函数的时候 如果有默认值 可以根据业务需求不传递
# my_print("小明", "001")
# my_print("小红", "002")
# my_print("小张", "003")


# 假如这个my_print的函数打印全班的人的信息 有80% 是20岁 但是 20% 年龄在25-30之间
# 如果执行函数的时候提供实参(本来有20,现在有30来替代20) 那么函数的形参使用实参;如果执行函数的时候没有提供实参 那么形参将使用默认值(缺省参数)
# my_print("老王", "010", 30)


# 在定义函数的时候某个形参使用了缺省参数 那么后面的形参 都需要用缺省参数,比如age是20,后面no也得有缺省参数
def my_print(name, age=20, no="001"):

print("名字:%s" % name)
print("学号:%s" % no)
print("年龄:%d" % age)
print("="*30)
------------------------------------------------

## 04. 函数的递归

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

### 4.1 递归函数的特点

**特点**

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

**代码特点**

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

示例代码

```python
def sum_numbers(num):

print(num)

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

sum_numbers(num - 1)

sum_numbers(3)

```

![002_递归调用示意图I](media/14993074876434/002_%E9%80%92%E5%BD%92%E8%B0%83%E7%94%A8%E7%A4%BA%E6%84%8F%E5%9B%BEI.png)


### 4.2 递归案例 —— 计算数字累加

**需求**

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

```python
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_递归调用示意图](media/14993074876434/002_%E9%80%92%E5%BD%92%E8%B0%83%E7%94%A8%E7%A4%BA%E6%84%8F%E5%9B%BE.png)

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

 

5。嵌套函数应用

------------------------------------------
# # 写一个函数打印一条横线
def print_one_line():
print("-"*10)

# 打印自定义行数的横线
def print_lines(num):
for i in range(num):
# 执行函数print_one_line
print_one_line()
print_lines(10)


# 函数求三个数的和
def add3num(a, b, c):
return a + b + c

# 定义函数求三个数的平均值
def average3num(num1, num2, num3):
ret = add3num(num1, num2, num3) # 用上面的求和函数,并且把平均值函数中的参数放进上面的函数
# 把和除以3
return ret / 3

result = average3num(10, 12, 17) #将3个值放入平均值函数,然后值再传入求和函数中
print(result)
------------------------------------------------------

6.拆包# 定义一个列表
# my_list = [1, 3.14, "hello", True]
# 可以获取列表中元素的值 但是可读性不强
# print(my_list[1])
# print(my_list[2])

# 拆包:变量和上面的值是一一对应的
# num, pi, my_str, my_bool = my_list
# print(pi)
# print(my_bool)
# num, pi, my_str, my_bool = [1, 3.14, "hello", True]


# 定义一个元组
# my_tuple = (1, 3.14, "hello", True)
# num, pi, my_str, my_bool = my_tuple
# print(pi)


# 定义一个字典
# my_dict = {"name":"老王", "age": 19}
# ret1, ret2 = my_dict
# 此时得到的是key 字典是无序的
# print(ret1, ret2)

# 一次定义多个变量
# num1 = 10
# num2 = 20
# num3 = 30
# num4 = 3.14
# # 变量名和值是一一对应
# num1, num2, num3, num4 = 10, 20, 30, 3.14
# print(num4)


# 元组 上节课学的返回一个元组
def deal_name_age(name, age):
# 处理后 姓名:小明 年龄:22
new_name = "姓名:%s" % name
new_age = "年龄:%d" % age
# 如果在函数内部 使用return 返回值1 返回值2,... 默认就是元组类型 不需要写小括号
return new_name, new_age
# 下面进行拆包
my_name, my_age = deal_name_age("小明", 20) #本是ret = deal_name_age9 ("小明",20);可直接
print(my_name, my_age)

###拆包 —— 交换两个数字

**题目要求**

1. 有两个整数变量 `a = 6`, `b = 100`
2. 不使用其他变量,**交换两个变量的值**

--------------------------------------------------

#解法1:使用其他的变量
a = 6
b = 100

c = a
a = b
b = c
print(a,b,c)

#解法2:不使用其他的变量
a = 6
b = 100
a = a + b
b = a - b
a = a - b


#解法3:使用到拆包
a = 6
b = 100
a, b = b, a #省略小括号,右边是个元组,其实是a, b = (b, a)
print(a,b)
-----------------------------------------
 
7.函数的文档说明

# 假设 len函数
# 函数的文档说明 -> 加的文档说明 是python
# help(len)
# len python内置函数 python创建

# 很多的时候需要程序员自己创建
# 自定义一个函数
# def add2num(num1, num2):
# return num1 + num2
#
# # 如果开发写的函数 没有文档说明 用help会打印函数上面的注释
# help(add2num)

# 自定义一个函数
def add2num(num1, num2):
"""
这个函数是用来计算两个数的和的
:param num1: 数字1
:param num2: 数字2
:return: 返回值是两个数字相加
"""
return num1 + num2

# 函数-----使用文档说明和单行注释来进行维护跟踪
def my_func(a, b):
# 文档说明
"""
:param a:
:param b:
:return:
"""
# 单行注释
num = 10

return a + b + num

 8.列表推导式
# 定义一个空列表
# my_list = []
# for i in range(1, 101):
# my_list.append(i)
#
# print(my_list)

# 使用列表推导式 快速创建一个列表,相当于上面的方法,前面的i是每次添加进去的
# my_list = [i for i in range(1, 31)]
# print(my_list)

# 反思 得到一个有30个哈哈的列表
# my_list = ["哈哈" for i in range(30)]
# print(my_list)

# 定义一个列表 保存数据[1, 50]之间的偶数
# my_list = []
# for i in range(1, 51):
# # 判断是否是偶数
# if i % 2 == 0:
# my_list.append(i)
#
# print(my_list)

# 列表推导式
# my_list = [i for i in range(1, 51) if i % 2 == 0]
# print(my_list)

posted on 2020-03-13 16:51  宝宝萌  阅读(444)  评论(0编辑  收藏  举报