我的Python学习笔记_Day10 函数2

文章目录

  • 1. 函数的返回值
      • 1) 返回值的作用
      • 2) 初学者如何判断?
      • 3) 怎么确定返回值?
      • 4) 获取函数的返回值
  • 2. 完整的函数调用过程
      • 1) 执行过程
      • 2) 内存变化
  • 3. 全局变量和局部变量
      • 1) 变量的作用域
      • 2) 全局变量
      • 3) 局部变量
      • 4) global和nonlocal
          • a. global
          • b. nonlocal
  • 4. 匿名函数
      • 1) 什么是匿名函数?
      • 2) 声明匿名函数
  • 5. 递归函数
      • 1) 什么是递归函数
      • 2) 递归怎么用
  • 作业

1. 函数的返回值

1) 返回值的作用

将函数里面的数据传递到函数外面

2) 初学者如何判断?

初学者怎么确定需不需要返回值:

看函数的功能完成后要不要产生新的数据

3) 怎么确定返回值?

函数声明时,函数体中,

return后面的值就是函数的返回值

若没有return,函数返回None

写法 说明 作用
return 关键字
只能写到函数体里
确定函数的返回值
结束函数

执行函数体的时候如果遇到return,函数直接结束,同时将return后面的值作为返回值返回

def sum_int(num1: int, num2: int):
    return num1 + num2

4) 获取函数的返回值

获取函数调用表达式的值即可

例:用 3) 中的函数

result = sum_int(5, 2) + 2
print(result)  # 结果:9

注:函数调用表达式就是函数调用语句
普通数据能做的事函数调用表达式就能做

上例子中,sum_int(5, 2) 的返回值是7,所以在语句中,和7的作用一模一样,可以直接进行运算

2. 完整的函数调用过程

day9中的函数调用过程没有涉及到返回值,这里完善一下

1) 执行过程

a. 回到函数声明位置

b. 传参 - 保证每个参数都有值

c. 执行函数体

d. 执行完函数体确定返回值
看执行完函数体的时候有没有遇到return
如果遇到了return,后面的值就是返回值
没有遇到就返回None

e. 回到函数调用的位置
(这个时候函数调用表达式的值才是函数的返回值)

2) 内存变化

函数的调用过程是一个压栈的过程

调用函数的时候系统会自动在栈区间为这个函数申请一个专用的内存区域,专门用来保存在函数中声明的变量和产生的数据

注:形参也是声明在函数中的变量

当函数结束的时候,这个内存区域会自动释放

销毁前会将返回值扔出来

3. 全局变量和局部变量

1) 变量的作用域

即变量可以使用的范围

2) 全局变量

python: 没有声明在函数中或者类中的变量都是全局变量

全局变量从声明开始到文件结束任何地方都可以使用

for b in range(4):
    c = 100
    pass
print(b, c)  # 结果是3 100  这里b、c都是全局变量

3) 局部变量

声明在函数中的变量就是局部变量

(形参也是局部变量)

作用域:从声明开始到函数结束

def func2(aa):
    pass
func2(100)
print(aa)  # 报错,NameError,aa没有被定义

ps:python里,函数中还能声明函数

4) global和nonlocal

global和nonlocal这两个关键字只能在函数体中使用

a. global
a = 100

def func4():
    a = 200
    print('函数中', a)

func4()
print('函数外', a)

# 结果:
# '函数中' 200
# '函数外' 100

出现上面这个现象的原因是:

a = 100 的这个a是全局变量

函数中,a = 200 的这个a是函数中的局部变量,是一个新的变量

函数结束时,值是200的局部变量a在内存里被释放

而原来的值是100的a还是原来的a

a = 100

def func4():
    global a  # 这个单独占一行!!!
    a = 200
    print('函数中', a)

func4()
print('函数外', a)

# 结果:
# '函数中' 200
# '函数外' 200
写法 说明
global 变量
变量 = …
函数中,在变量赋值前,
在函数中声明此变量为全局变量
b. nonlocal

使用场景:

在局部的局部中,修改局部的值

def func5():
    a = 100
    
    def func6():
        a = 200  # 这里也不行
        print(a)
    
    func6()
    print(a)
    
# 结果:200  100

在func6中,修改a的值也不行
因为a=200的a是func6的局部变量
同global一样,只是nonlocal在局部中使用

def func5():
    a = 100

    def func6():
        nonlocal a
        a = 200  # 这里可以
        print(a)

    func6()
    print(a)

func5()
# 结果:200  200

*但是nonlocal不能声明,只能修改!!!

def func5():
    a = 100
    
    def func6():
        nonlocal b  # 这里报错
        b = 200
        print(a)
    
    func6()
    print(a)
写法 说明
nonlocal 变量
变量 = …
作用:
在子函数中,修改母函数的局部变量的值

nonlocal几乎不用,因为函数中声明函数已经很少见了,在这种情况下还有在子函数中修改母函数的局部变量,更罕见了

4. 匿名函数

1) 什么是匿名函数?

没有名字的函数

匿名函数还是函数,普通函数中,除了声明的语法以外,其他常用语法基本都适用于匿名函数

注:不支持普通函数中形参的参数类型说明

2) 声明匿名函数

lambda  参数列表:返回值
写法 说明
lanmbda 关键字,固定写法
参数列表 形参:参数1,参数2,…
固定写法,不产生缩进
返回值 相当于普通函数的return语句

相当于:

def (参数列表):
	return 返回值

随堂练习:

用匿名函数实现两个数求和

func1 = lambda num1, num2: num1 + num2  # 声明
print(func1(10, 20))  # 结果:30

因为匿名,所以没法直接调用,这里暂时用一个变量去接

随堂练习:

写一个匿名函数判断指定的年是否是闰年

loop_year = lambda year: (year % 4 == 0 and year % 100 != 0) or year % 400 == 0

5. 递归函数

1) 什么是递归函数

在声明函数时调用函数本身的函数

即在声明的时候调用自己

def func1():
    func1()  # 报错

因为每次执行函数都会压栈,无限压栈内存怎么都不够

递归可以实现循环效果

原则上,除了死循环,其他的循环用递归都可以实现

递归比循环会消耗多的多的内存空间

2) 递归怎么用

使用递归的套路:

a. 设置临界值  -  循环结束的条件(保证函数在临界值结束)
b. 找关系  -  找f(n)和f(n-1)的关系
c. 假设函数的功能已经实现,通过f(n-1)去实现f(n)的功能

栗子:写一个递归函数,计算1+2+3+…+N

def sum_num(n: int):
    # 找临界值
    if n == 1:
        return 1

    # 找关系
    """
    f(n): 1+2+3+...+n
    f(n-1): 1+2+3+...+n-1
    f(n) = f(n-1) + n
    """

    # 用f(n-1)实现f(n)的功能
    return sum_num(n - 1) + n

n=5时的实现过程:

我的Python学习笔记_Day10 函数2_第1张图片

这里的 yt_sum() 和上面的 sum_num() 一样

随堂练习:

写一个递归函数,求斐波那契数列的第n个数

1,1,2,3,5,8,13,21…

def fibonacci(n: int):

    # 找临界值
    if n == 1 or n == 2:
        return 1

    # 找关系
    # f(n) = f(n - 1) + f(n - 2)
    
    # 用f(n-1)实现f(n)的功能
    return fibonacci(n - 1) + fibonacci(n - 2)

练习:

写一个递归函数:

n = 4
*
**
***
****

自己做的:

def star(n: int):
    if n == 1:
        return '*'
    return star(n - 1) + '\n' + '*' * n

老师答案:

def print_star(n):
    if n == 1:
        print('*')
        return
    print_star(n - 1)
    print(n * '*')

作业

完善昨天的作业,尝试写出交互式学生管理系统

学生管理系统见day10的周末篇

你可能感兴趣的:(Python学习笔记)