Python 5.函数作用域与递归(基础篇)

  • 本章大纲:
  • -变量作用域-
  • 变量由作用范围限制
  • 两种不同的作用域:
  • 全局(global):在函数外部定义
  • 局部(local):在函数内部定义
  • 变量的作用范围
  • 全局变量
  • 在整个程序范围都有效
  • 全部变量可以在局部范围里面使用
  • 局部变量在局部范围内可以使用
  • 局部变量无法在全局范围内使用
  • LEGB原则
  • L(Local)局部作用域
  • E(Enclosing function locale)外部嵌套函数作用域(命名空间)
  • G(Global module)全局变量,函数定义所在模块的命名空间
  • B(Buildin):python内置作用域或又名 内部建模的命名空间
  • -递归函数-
  • 函数直接或者间接调用自身
  • 优点:简洁,容易理解
  • 缺点:对递归深度有限制,过多会导致消耗资源
  • python对递归深度有限制(自我调用997次),超出限制自动报错
  • eval()函数
  • exec()函数




全局变量和局部变量案例如下
glo = "我是全局"
def func():
    print(glo)  # 在函数内部调用全局变量
    print("*"*20)
    loc = "我是局部"  # 定义局部变量
    print(loc)# 在函数内部调用局部变量

func() #调用函数,查看函数内部调用内容
print("下面为全局范围的调用")
print(glo)# 在全局范围里调用全局变量
print(loc)# 在全局范围里调用局部变量,但是无法调用,会报错
结果如下:
我是全局
Traceback (most recent call last):
********************
我是局部
  File "D:/图灵/2.基础语法/测试.py", line 11, in <module>
下面为全局范围的调用
    print(loc)# 在全局范围里调用局部变量,但是无法调用,会报错
我是全局
NameError: name ‘loc‘ is not defined


-局部变量提升为全局变量-
  • 使用global
  • 使用格式:
  • global val (val为局部变量名字)
 案例如下 案例条件我复制了上面的例子进行修改,把loc能在全局范围里调用
glo = "我是全局"
def func():
    print(glo)  #在函数内部调用全局变量
    print("*"*20)
    global loc  #为loc局部变量提升为全局变量
    loc = "我是局部"  #定义局部变量
    print(loc) #在函数内部调用局部变量

func() #调用函数,查看函数内部调用内容
print("下面为全局范围的调用")
print(glo)# 在全局范围里调用全局变量
print(loc) #不知道什么原因,尽管可以调用,但是pycharm这里还是显示变量为红色(报错),但是可以运行

结果如下:
我是全局
********************
我是局部
下面为全局范围的调用
我是全局
我是局部


-查看整个程序有多少局部或全局变量-
  1. 通过globals和locals显示
  2. global和locals都为内建函数(系统给的)
 案例如下 因为程序内部可能没有局部函数,所以我们先定义一些
a = 1
b = 2
def func(d,e):
    c = 3
    print(locals())
    print(globals())

func(100,200)
结果如下:
# 因为全局变量太多了 我这里只例举一些结果就行,你们可以直接copy代码测试一下
{‘d‘: 100, ‘e‘: 200, ‘c‘: 3}
{‘__name__‘: ‘__main__‘, ‘__doc__‘: None, ‘__package__‘.........}

最终打印讲解:
  1. 局部变量为 d e c,这样我们可以发现从调用里面传入的参数值也是函数内部的局部变量,而a,b是我们在全局范围里定义的,所以并没有定义
  2. 全局变量则一大堆,因为这些都是系统附带的,一个程序的允许,需要一推东西,而这堆东西系统都准备好了

 -eval()函数-
  • 把一个字符串当成一个表达式来执行,返回表达式执行后的结果
  • 语法:
  • eval(string_code,globals=None,locals=None)
 -exec()函数-
  • 跟eval功能相似,但是不返回结果
  • 语法:
  • exec(string_code,globals=None,locals=None)
 使用字符串进行算术 案例如下
x = 199
y = 1
z1 = x + y  # 使用值来计算
z2 = eval("x+y") # 用字符串来计算
 打印比较一下两个计算是否相等
print(z1)
print(z2)
print(z1 == z2) #值为true
print(type(z2)) #返回值的类型为int
结果如下:
200
200
True
<class ‘int‘>

使用exec来计算 案例如下
x = 199
y = 1
z1 = x + y
 在exec中打印结果,注意看字符串引号的用法 对比exec执行过程和执行结果
z2 = exec("print(‘x+y:‘,x+y)")
#在打印过程中,exec内部的print先打印,因为还没经过exec所以带有结果,我们可以看到结果为200
print(z1)
print(z2)
print(z1 == z2) #因为最终结果返回值为None,所以不相等
print(type(z2)) #因为结果是None,所以无类型
结果如下:
x+y: 200
200
None
False
<class ‘NoneType‘>


 -递归函数-
  • 函数直接或者间接调用自身
  • 优点:简洁,容易理解
  • 缺点:对递归深度有限制,过多会导致消耗资源
  • python对递归深度有限制(自我调用997次),超出限制自动报错
 测试python递归深度的限制
 a = 1
 def func():
     global a
     a += 1
     print(a)
     func()

 func()
结果如下:
# 初始递归深度为997,太多了,我也跟上面的一样,列举打印,你们可以复制代码尝试
1
2
3
4
......
995
996
997
Traceback (most recent call last):
  File "D:/图灵/2.基础语法/测试.py", line 11, in <module>
    func()
  File "D:/图灵/2.基础语法/测试.py", line 8, in func
    func()
  File "D:/图灵/2.基础语法/测试.py", line 8, in func
    func()
  File "D:/图灵/2.基础语法/测试.py", line 8, in func
    func()
  [Previous line repeated 992 more times]
  File "D:/图灵/2.基础语法/测试.py", line 7, in func
    print(a)
RecursionError: maximum recursion depth exceeded while calling a Python object
 所以在使用递归时候一定要注意结束条件,否则会崩溃+浪费资源
  • 举一个带有结束条件的例子
  • 斐波那契数列
  • 一列数字,第一个值是1, 第二个也是1, 从第三个开始,每一个数字的值等于前两个数字出现的值的和
  • 数学公式为: f(1) = 1, f(2) = 1, f(n) = f(n-1) + f(n-2)
  • 例如: 1,1,2,3,5,8,13.。。。。。。。。
 n表示求第n个数子的斐波那契数列的值
def func(n):
     # 进行第一和第二次值为1 2 的递归时如果不使用指定返回值的话,后面无法进行递归运算
    if n == 1:
        return 1
    if n == 2:
        return 1
    return func(n-1)+func(n-2)
     如果n等于1,不加判断使其获得返回值时,表达式为 func(1-1)+func(1-2) 则func(0)和func(-1),慢慢变负数,无法获得返回值,最终超出递归深度     简单来说,两个判断句就是用来修正n不会变成负数打印结果:
print(func(3))   #1,1,2 我求的是第三位,所以等于2

结果如下:
2

  



  -递归修正问题-
  • 如果n一开始就为负数,如何修正
  • 修正问题:
  • 1.让传入的值去除负号
  • 2.让传入的值不再进入递归
  • 两种方法都行
# 其中一种方法而已
def fab(n):
    if n >= 0:
        if n <= 2:
            return 1
        else:return fab(n-1)+fab(n-2)
print(fab(-4))
结果如下:
None
 -递归深度限制问题-
  • 使用sys库里面的setrecursionlimit(val)函数可以解决
 import sys sys.setrecursionlimit(1000000)  我这里直接将递归深度的限制改为1000000次

关于递归修正问题,如果有博客园的大佬有其他见解,请一定加我QQ为我讲解,谢谢

文笔不好,仅供参考


要有错误或者有其他更多的见解,欢迎大家加我QQ384435742来交流


想第一时间看更新的文章,请关注,谢谢



原文地址:https://www.cnblogs.com/ggqjlzt/p/9693351.html

时间: 2024-10-12 01:00:05

Python 5.函数作用域与递归(基础篇)的相关文章

零基础掌握百度地图兴趣点获取POI爬虫(python语言爬取)(基础篇)

实现目的:爬取昆明市范围内的全部中学数据,包括名称.坐标. 先进入基础篇,本篇主要讲原理方面,并实现步骤分解,为python代码编写打基础. 因为是0基础开始,所以讲得会比较详细. 如实现目的所讲,爬取昆明市全部中学数据,就是获取百度地图上昆明市范围内所有关键字带中学的地理信息数据(兴趣点). 怎么把百度地图上的数据抓取下来呢? 以下是教程: 本篇目录如下: 1. 百度地图开放平台注册,AK获取 2.关于ak的说明 3.请求URL说明 4.百度地图坐标拾取器 5.以坐标范围获取兴趣点POI 6.

自动化运维Python系列(一)之基础篇

Python介绍 Python是由创始人吉多·范罗苏姆(Guido van Rossum)在1989年圣诞节假期期间,为了打发时间,构思出来的一个新的脚本解释器.由于Guido在开发Python语言过程中,借鉴了很多ABC语言特性,所有后来包括Guido自己也那么认为,Python语言的前身就是ABC语言. Python是一门面向对象的.动态解释型强定义语言:Python崇尚简洁.优美.清晰,是一门优秀的被广泛使用的语言. 在2015年以前,最流行的Python版本还是2.4,但是由于Pytho

python学习笔记三之下(基础篇)

文件操作 打开文件 open(name[,mode[,buffering]])   open函数使用一个文件名作为强制参数,然后返回一个文件对象.python 3.5 把file()删除掉 with open(somefile.txt,'r') as files: do_something(files) with 语句打开文件并把值赋值到变量,之后可以对文件操作.文件在语句结束之后会自动关闭,即使异常引起也会退出. 文件模式 r   #只读模式(默认) w(>) #写模式 a (>>) 

Python的函数参数和递归参数

位置参数 def power(x): return x*x; 默认参数 指的是在函数定义的时候,就赋予一些参数默认值,在调用这个函数的时候不必多次传入重复的参数值. 如定义一个多次输出同一个年龄阶段和同一个城市的学生的姓名和性别. def info(name,gender,age=20,city='sichuan'): print('name:', name) print('gender:', gender) print('age',age) print('city',city) info("x

python学习笔记三之上(基础篇)

深浅copy以及赋值 对于字符串和数字而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. import copy n1 = 10242048 #n1 = 'hahahaha' #赋值n2 = n1#浅copy n3 = copy.copy(n1) #深copyn4 = copy.deepcopy(n1)print(id(i),id(i1)) #打印内存地址5787536 5787536print(id(i),id(i2))5787536 5787536print(id(i),id(

python学习笔记三之中(基础篇)

函数 内置函数 常用的内建函数: type()  列出指定对象的类型 help()  能够提供详细的帮助信息 dir()    将对象的所有特性列出 vars()  列出当前模块的所有变量 file,doc,name __file__  列出文件位置 __doc__  文档字符串 __name__ 被执行的脚本,name == __main__ if __name__ == "__main__": print("hello") int() abs() max() m

Javscript的函数链式调用基础篇

我们都很熟悉jQuery了,只能jQuery中一种非常牛逼的写法叫链式操作: $('#div').css('background','#ccc').removeClass('box').stop().animate({width:300}) 在原生js中,链式调用还可以这样用 function show(str) { console.log(str); return show; } show(123)(456)(789); // 控制台打印结果 // 123 // 456 // 789 (fun

3.关于python函数,以及作用域,递归等知识点

一.使用函数编程的好处. 大大的提高了代码的重用行,重复的逻辑或者操作,可以定义到一个函数里,多次调用. 下面是关于提高代码重用性的例子. 现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码. while True: if cpu利用率 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 i

Python成长笔记 - 基础篇 (四)函数

1.面向对象:类(class) 2.面向过程:过程(def) 3.函数式编程:函数(def)----python 1.函数:http://egon09.blog.51cto.com/9161406/1834777 编程语言中函数定义:函数是逻辑结构化和过程化的一种编程方法. 12345678910111213 python中函数定义方法: def test(x): "The function definitions" x+=1 return x def:定义函数的关键字test:函数名