首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python 之父解析器系列之五:左递归 PEG 语法

曾几次提及左递归是一块绊脚石,是时候去解决它了。基本问题在于:使用递归下降解析器时,左递归会因堆栈溢出导致程序终止。 【这是 PEG 系列第 5 部分。...oracle_expr() 函数将读取该全局变量,装饰器操纵着它: saved_result = None def oracle_expr(): if saved_result is None...决定性洞察(这是自己,虽然可能不是第一个想到)是我们可以使用记忆缓存不是全局变量,将一次调用结果保存到下一次,然后我们不需要额外oracle_expr() 函数——我们可以生成对 expr...第 3 篇文章中创建基础结构另一个不错属性是它更容易检查新结果是否长于旧结果:mark() 方法将索引返回到输入标记符数组中,因此我们可以使用它,而非上面的parsed_length 。...至于下周,打算论述语法中添加“动作”(actions),这样我们就可以为一个给定备选项解析方法,自定义它返回结果不是总要返回一个 Node 实例)。

79830
您找到你想要的搜索结果了吗?
是的
没有找到

Python 工匠:让函数返回结果技巧

除了通过 return语句返回内容,函数内还可以使用抛出异常(raise Exception)方式来“返回结果”。 接下来,将列举一些函数返回相关常用编程建议。 编程建议 1....抛出异常,不是返回结果与错误 在前面提过,Python 里函数可以返回多个值。基于这个能力,我们可以编写一类特殊函数:同时返回结果与错误信息函数。...(结果, 错误信息)”后,整个错误流程处理乍看上去变化不大,但实际上有着非常多不同,一些细节: 新版本函数拥有更稳定返回值类型,它永远只会返回 Item 类型或是抛出异常 虽然在这里鼓励使用异常,...合理使用“空对象模式” 在前面提到函数可以用 None 值或异常来返回错误结果,但这两种方式都有一个共同缺点。...缓存工具函数来降低递归层数 总结 在这篇文章中,虚拟了一些与 Python 函数返回有关场景,并针对每个场景提供了优化建议。

2.2K30

Python 工匠:让函数返回结果技巧

所以,了解如何优雅函数返回结果,是编写好函数必备知识。Python 函数返回方式Python 函数通过调用 return 语句来返回结果。...除了通过 return 语句返回内容,函数内还可以使用抛出异常(raise Exception)方式来“返回结果”。接下来,将列举一些函数返回相关常用编程建议。---编程建议1....抛出异常,不是返回结果与错误在前面提过,Python 里函数可以返回多个值。基于这个能力,我们可以编写一类特殊函数:同时返回结果与错误信息函数。...图片 系列第 4 篇文章“容器门道” 里详细分析过这个模式,更多细节可以访问文章,搜索 “写扩展性更好代码” 查看。7. 限制递归使用当函数返回自身调用时,也就是 递归 发生时。...缓存工具函数来降低递归层数---总结在这篇文章中,虚拟了一些与 Python 函数返回有关场景,并针对每个场景提供了优化建议。

4.4K31

Python 工匠:让函数返回结果技巧

除了通过 return 语句返回内容,函数内还可以使用抛出异常(raise Exception)方式来“返回结果”。 接下来,将列举一些函数返回相关常用编程建议。 编程建议 1....抛出异常,不是返回结果与错误 在前面提过,Python 里函数可以返回多个值。基于这个能力,我们可以编写一类特殊函数:同时返回结果与错误信息函数。...(结果, 错误信息)”后,整个错误流程处理乍看上去变化不大,但实际上有着非常多不同,一些细节: 新版本函数拥有更稳定返回值类型,它永远只会返回 Item 类型或是抛出异常 虽然在这里鼓励使用异常,...合理使用“空对象模式” 在前面提到函数可以用 None 值或异常来返回错误结果,但这两种方式都有一个共同缺点。...缓存工具函数来降低递归层数 总结 在这篇文章中,虚拟了一些与 Python 函数返回有关场景,并针对每个场景提供了优化建议。

2.2K40

Python 工匠:让函数返回结果技巧

除了通过 return 语句返回内容,函数内还可以使用抛出异常(raise Exception)方式来“返回结果”。 接下来,将列举一些函数返回相关常用编程建议。 编程建议 1....抛出异常,不是返回结果与错误 在前面提过,Python 里函数可以返回多个值。基于这个能力,我们可以编写一类特殊函数:同时返回结果与错误信息函数。...(结果, 错误信息)”后,整个错误流程处理乍看上去变化不大,但实际上有着非常多不同,一些细节: 新版本函数拥有更稳定返回值类型,它永远只会返回 Item 类型或是抛出异常 虽然在这里鼓励使用异常,...合理使用“空对象模式” 在前面提到函数可以用 None 值或异常来返回错误结果,但这两种方式都有一个共同缺点。... 缓存工具函数来降低递归层数 总结 在这篇文章中,虚拟了一些与 Python 函数返回有关场景,并针对每个场景提供了优化建议。

1.7K10

日拱一卒,假装在上伯克利,CS61A Lab05

一定要用递归,可以当做是递归入门题。 关于tree相关一些函数lab05.py底部。大家不要直接访问tree中数据,而是要遵守数据抽象规范,使用对应函数获取相应值。...新树上每个节点都是传入两棵树上同样位置节点之和。如果一个节点只一棵树上出现,答案中一样也会出现。 提示:你也许想要使用zip函数来遍历两个sequence。...既然我们要用None来修补空缺,那么势必就会导致递归时候传入t1和t2这两个参数可能会有None值出现。处理方式也很简单,如果t1是None,那么合并之后结果就是t2。...由于我们递归开头已经处理了入参可能存在None情况,所以大胆地递归就行了。而且本题不可能出现t1和t2都是None情况,想想看为什么。...不得不说这一次实验题目还是挺有意思,尤其是对于递归掌握得不是很好同学,相信练习之后一定可以获得长足进步。 喜欢本文的话不要忘记三连~

1K30

日拱一卒,伯克利大招,带你写一个解释器(一)

我们返回结果是Pair(scheme_read(src), read_tail(src)),这是一个经典递归结构。 前文说了,else分支表示我们读到了一个新表达式开头。...,进行测试: python3 ok -q 03 当完成这个部分开发之后,你解释器将能够访问到一些内置过程,如: 不过目前还只是访问,想要能够调用这些过程,还需要我们继续开发。...,除此之外还有一些其他函数你可能会用到: check_procedure函数,当输入参数不是一个scheme过程时会报错。...比如(+2 2)这个表达式,我们拿到expr.first只是+,add函数才是我们想要。这个函数需要我们从env这个frame当中获取,好在题目当中已经提示我们了,可以使用递归进行获取。...为什么一定要用递归不是再调用一次env.lookup呢?因为expr.first也可能是一个嵌套表达式,这种情况就没办法通过env.loopup获取了。所以一定要递归

72521

python之抽象一

>>>x >>> 没东西,仔细看看 >>>print x None 所以所有的函数返回了东西,:当不需要他们返回值得时候,它们就返回None。 千万不要被默认行为所迷惑。...函数局部名称-----包括参数在内-----并不和外面的函数名称冲突。 1.为什么想要修改参数 使用函数改变数据结构是将程序抽象化好方法。...不是要收集参数,而是分配它们“另一端”。使用*运算符就简单了------不过是调用不是定义时使用: >>>add(*params) 3 对于参数列表来说工作正常,只要扩展部分是最新就可以。...首先,定义了一些函数: def story(**kwds): return 'Once upon a time,there was a ' \ '%(job)s called %(name)s.'...,因为根据官方Python文档说法,结果是未定义,换句话说,可能得不到想要结果

44610

Python 之父再发文:构建一个 PEG 解析器

结果可能不是一个很棒通用型 PEG 解析器生成器——这类生成器已经有很多了(例如 TatSu,写于 Python,生成 Python 代码)——但这是一个学习 PEG 好办法,推进了目标,即用由...初稿解析器中,解析函数返回 True 或 False。那对于理论计算机科学来说是好(解析器要解答那类问题是“语言中这个是否是有效字符串?”)...,但是对于构建解析器却不是——相反,我们希望用解析器来创建一个 AST。 所以我们就这么办,即让每个解析方法成功时返回 Node 对象,失败时返回 None 。...在这里,有必要介绍解析方法一个重要需求:一个解析方法要么返回一个 Node,并将标记器定位到它能识别的语法规则最后一个标记之后;要么返回 None,然后保持标记器位置不变。...还作了个小弊:expr 是左递归,但我解析器用了右递归,因为递归下降解析器不适用于左递归语法规则。 有一个解决方案,但它还只是一些学术研究上课题,想以后单独介绍它。

1.2K20

《Python基础教程》第六章--读书

python有些函数却并不返回任何东西。 python函数就是函数,即便它从学术上讲并不是函数。...x貌似没东西,但是其实有个很熟悉None。所以,所有的函数的确否返回了东西:当不需要它们返回值得时候,它们返回None。看来刚才“有些函数不是真的是函数说法有些不公平了。...写在def语句中函数名后面的变量通常叫做函数形参(parameter),调用函数时候提供值是实参(argument)或者成为参数。 能改变参数吗?...,不是程序运行时。...看如下例子: #定义函数 def add(x,y): return x+y 有一个由两个数字组成元祖:params=(1,2) 此时使用*元算符就简单多了——不过是调用不是定义时使用,

69510

Python 递归函数返回值为 None 解决办法

使用 Python 开发过程中,避免不了会用到递归函数。但递归函数返回值有时会出现意想不到情况。 下面来举一个例子: >>> def fun(i): ... ...return i ... >>> r = fun(0) >>> print(r) 比如上面这段代码,乍一看没什么问题,但返回值并不是我们期望 5,而是 None。...>>> print(r) None 要解决这个问题也简单,就是执行递归调用时候,加上 return 语句。 修改之后代码如下: >>> def fun(i): ... ...return i ... >>> r = fun(0) >>> print(r) 5 现在输出结果就符合我们预期了。...最后补充一句,如果想要了解这背后深层原理,可以看看函数调用栈相关资料,这里就不过多介绍了。 本文就到这里了,如果觉得有用的话欢迎点赞,转发和关注,谢谢。

65600

Python3.0科学计算学习之函数

return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式return相当于返回 None。    ...同一个参数不能传两个值 z=3 e=subtract(x2=z,x1=5) #在这里函数调用中,实参时通过名称赋值给形参不是通过位置 传参规则: 实参角度:   规则:按位置传值必须在按关键字传值前面...因此每次调用函数都将会消耗一些内存,当内存爆满就自然就挂了。这个函数递归为无穷递归,就好比一个while死循环。...由于栈大小不是无限,所以递归调用次数越多会导致栈溢出。) 为了防止栈溢出;我们可以使用尾递归优化,尾递归是指:函数返回时候,调用自身本身,并且return语句不能包含表达式。...装饰器函数外部函数传入要装饰函数名字,返回经过修饰后函数名字;内层函数(闭包)负责修饰被修饰函数

1.2K20

什么是递归--What does resursion mean?

第一要素:明确你这个函数想要干什么 对于递归觉得很重要一个事就是,这个函数功能是什么,他要完成什么样一件事,而这个,是完全由你自己来定义。...也就是说,我们需要找出当参数为啥时,递归结束,之后直接把结果返回,请注意,这个时候我们必须能根据这个参数值,能够直接知道函数结果是什么。...第三要素:找出函数等价关系式 第三要素就是,我们要不断缩小参数范围,缩小之后,我们可以通过一些辅助变量或者操作,使原函数结果不变。...回答:这个问题回答可以是这样,如果递归函数需要返回一个数值或者对象,那么递归深度决定了return次数,return起到了提前结束方法作用;另一方面,不是所有的函数都有返回值,递归函数也是可以没有返回脚本函数...一个斐波那契数列最简单情况就是求第1个和第二个。这不是看了递归解法之后,发现原来最先出结果(调用return是1,2对应斐波那契数,于是我们就用方法返回时间线角度去考虑问题。

55620

算法之递归

思考了之后大概明白了一些(难以言表),确实可以在内部调用,最后可能脑袋里会有一个类似“洋葱”结构,函数包裹者函数,上面那种递归是最简单一种形式了,差不多能想明白。...因为虽然有 return 语句但是返回函数执行,还要执行返回这个函数,因此最外层 sum 函数并没有执行完,他需要等待里面的函数执行完才算执行完,里面的函数又会 return 出更里面的函数执行...然后执行 a 函数后面的语句,将 c 函数入栈...... 案例 递归算法中应用十分广泛,相较于循环迭代,递归显得更加优雅直观,代码易读性好一些。...一般递归函数中,是首先执行递归调用,然后获取递归调用返回值并计算结果递归首先执行计算,然后执行递归调用,将当前步骤结果传递给下一个递归步骤,尾递归也是为了优化递归算法。...1 : n * factorial(n - 1); } 虽然这个函数尾部调用,但它不是递归。上面已经说了,尾递归首先会执行计算,然后执行调用。

70010

day 17 - 1 递归函数

递归函数 什么是递归   了解什么是递归函数中调用自身函数   最大递归深度默认是 997/998 —— 是 python 从内存角度出发做得限制   能看懂递归   能知道递归应用场景   ...初识递归 —— 二分法例子   算法 —— 二分查找算法   三级菜单 —— 递归实现 我们先来看一个简单递归函数 #可以执行下,看下与递归函数执行结果有什么不同 while True:...+ 2 # age(3) 返回结果加 2 得到 44,返回给 age(1) def age(3): if 3 == 4: return 40 elif 3 >0...返回值 1、不要只看到return就认为已经返回了。要看返回操作是递归到第几层时候发生,然后返回给了谁。 2、如果不是返回给最外层函数,调用者就接收不到。...,因为我们希望最后结果只是一个我们想要值 k = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

34410

如果你还不会决策树,那你一定要进来看看

每到一个中间节点都会面临一次判断,根据判断结果选择下一个子树。树上叶子节点代表一种分类,当数据到了叶子节点,这个叶子节点值就代表它分类结果。...那么最后我们想要实现什么效果呢?当然是得到准确率越高越好,根据决策树原理,树上每一个叶子节点代表一个分类。...这里有一个小细节, 根据ID3算法定义,每一次切分选择是特征,不是特征取值。并且被选中作为切分特征特征每一个取值都会建立一棵子树,也就是说每一个特征决策树当中都只会最多出现一次。...为了方便编码,我们把预测值Y放在特征最后,并且返回这三个特征名称,方便以后用来建树。 我们运行一下数据查看一下结果: ? 下面,我们实现计算集合信息熵函数。...这个预测函数也简单,它介绍一条数据以及我们训练完树结构,返回分类结果

55230

python中函数

# 调用函数 MYFirstFunction() # 运行结果: 这是创建第一个函数 表示很鸡冻。。。。。...add1函数使用print调用,但是代码中有一个return内置BIF函数返回给add1,所以使用print可以打印出信息。...return (num1 + num2) add(999,150) print(add1(7,8)) # 结果如下: 计算结果如下: 1149 15 4.函数一些名词 4.1 形参、...None python是可以返回多个值,我们可以想到列表,列表中使用逗号是可以变为元组,如下例,我们可以看到python中return是把这组数据打包成一个数据返回...;Fun2中x和Fun1中x不是一个变量,和之前全局变量和局部变量中讲到一样,python函数中定义一个全局变量,python通过shadowing方式来屏蔽掉这个全局变量,创建一个和全局变量相同变量

1.7K10
领券