CPython:表达式的求值顺序(evaluation order)

相关阅读

Pythonicon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12403403.html?spm=1001.2014.3001.5482


C中表达式的求值

        C语言针对表达式的计算,设置了操作符的优先级和结合性这两个特性,优先级用于解析不同优先级的符号,结合性用于解析相同优先级的符号。但是这两个特性并不能完全确定表达式的计算顺序,这就给编译器留下了一定的优化的空间,下面举例说明这一点。假设有如下所示的简单表达式。

例1
1 + 2 + 3

        C语言编译器在语法分析时会构建一个语法分析树,类似图1所示的二叉树结构。

图1 语法分析树

        在图1中,1+2整体作为一个子表达式成为了+操作符的左操作数,这是操作符的结合性导致的结果。这个语法分析树保证了,3和1+2会在根节点"+"前求值,1和2会在"+"的左子节点"+"前求值。但是,这并没有保证3和1+2的求值顺序,也没有保证1和2的求值顺序,具体地来说编译器可能选择先对3求值,随后对1+2求值,在对1+2求值时,先对2求值,再对1求值;也可能选择先对1+2求值,在对1+2求值时,先对1求值,再对2求值,最后对3求值....还有其他情况。

        这看似对最终表达式结果并没有什么影响(不管哪种求值顺序,结果都是6),但如果将简单的操作数换成函数调用,则会出现不同的情况,如下例所示。

例2
func1()+func2()+func3()int func1()
{printf("This is func1.\n");return 1; 
}int func2()
{printf("This is func2.\n");return 2; 
}int func3()
{printf("This is func3.\n");return 3; 
}

        在这个例子中,三个函数的执行顺序是不确定的,可能是func1、func2、func3,可能是func2、func1、func3,可能是func3、func1、func2,可能是func3、func2、func1。这就导致了printf语句的执行也是不确定的。 

        下面再看一个更复杂的例子。

例3
1 + 2 * 3

        在这个例子中,由于"*"的优先级大于"+", 2*3整体作为子表达式会成为"+"的右操作数。解析得到的语法分析树如下图2所示。

图2 语法分析树

        在这个例子中,2与3的乘法毫无疑问是会在与1的加法前进行的,但是对1、2、3的求值顺序是不确定的,可能是先对1求值,随后对2*3求值,在对2*3求值时,先对2求值,再对3求值;可能是先对2*3求值,在对2*3求值时,先对3求值,再对2求值,最后对1求值...还有其他情况。

        在这个简单的例子里,不同的求值顺序对结果没有影响,但如果将1、2、3换成func1、func2、func3,分析是类似的,即三个函数的执行顺序是不确定的(至少是不完全确定的)。

Python中表达式的求值

         Python中规定了表达式的求值顺序是从左到右的。就拿上面的例1举例,1+2子表达式一定在3之前求值,而1一定在2之前求值。用数据结构的语言来说,Python保证了在一个语法分析树中,表达式的求值是后序遍历的,即先求值左子节点,后求值右子节点,最后根据操作符求值整个表达式。下面来看一个例子。

例4
func1 + func2 * (func3 - func4)

        根据运算符的优先级,这个表达式被解析为图3所示的语法分析树。

图3 语法分析树 

        根据后序遍历的定义,这四个函数的执行顺序为:func1、func2、func3、func4。详细说就是,"+"的左操作数func1一定会在右操作数func2 * (func3 - func4)前求值;"*"的左操作数func2一定会在右操作数(func3 - func4)前求值;"-"的左操作数func3一定会在右操作数func4前求值。

        不止是针对表达式的求值,在Python中表达式列表的求值顺序也是确定的。表达式列表的定义如下所示,即为多个由","分隔的表达式,在函数调用、多变量赋值、函数返回中都有运用。

expression_list ::=  expression ("," expression)* [","]

        在如下例的函数调用中,求值的顺序是func1、func2、func3、func4、func5,其中func1也可以被求值,前提函数func1的返回值是一个函数名。

例5
func1(func2, func3, func4, func5)

        在如下例的多变量赋值中,求值的顺序是func1、func2、func3。

a, b, c = func1(), func2(), func3()

        在如下例的函数返回中,求值的顺序是func1、func2、func3.

return func1(), func2(), func3()

         实际上,后两种情况下,表达式列表在被求值后会变成一个包含各表达式求值结果元组,在多变量赋值操作中,元组内的各个元素被赋值给对应的目标变量;在函数返回中,return语句返回一个元组。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/467694.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux环境下配置HTTP代理服务器教程

大家好,我是你们可爱的Linux小助手!今天,我将带你们一起探索如何在Linux环境下配置一个HTTP代理服务器。请注意,这不是一次火箭科学的实验,而是一次简单而有趣的冒险。 首先,我们需要明确什么是HTTP代理服…

消息中间件面试篇

消息中间件 RabbitMQ 消息不丢失 可能导致消息丢失的情况: 生产者发送消息丢失消息队列宕机消费者服务宕机,未接收到消息 生产者确认机制 该机制解决了生产者发送消息有可能丢失的问题。 RabbitMQ提供了publisher confirm机制来避免消息发送到MQ过程…

【python量化交易】qteasy使用教程02 - 获取和管理金融数据

qteasy教程2 - 获取并管理金融数据 qteasy教程2 - 获取并管理金融数据开始前的准备工作获取基础数据以及价格数据下载交易日历和基础数据查看股票和指数的基础数据下载沪市股票数据从本地获取股价数据生成K线图 数据类型的查找回顾总结 qteasy教程2 - 获取并管理金融数据 qtea…

【见微知著】OpenCV中C++11 lambda方式急速像素遍历

学习《OpenCV应用开发:入门、进阶与工程化实践》一书 做真正的OpenCV开发者,从入门到入职,一步到位! C11 lambda语法 C11中引入了lambda表达式,它支持定义一个内联(inline)的函数,作为一个本地的对象或者…

如何才能学好JVM?——零基础入门篇

1. JVM是什么? JVM是Java Virtual Machine的简称,它是一个虚拟的计算机,专门为执行Java程序而设计。 你可以想象它是一个能够运行Java字节码的平台,无论你的程序在Windows、Mac还是Linux上,它们都能通过JVM在这些系统…

腾讯云4核8G服务器能支持多少人访问?

腾讯云4核8G服务器支持多少人在线访问?支持25人同时访问。实际上程序效率不同支持人数在线人数不同,公网带宽也是影响4核8G服务器并发数的一大因素,假设公网带宽太小,流量直接卡在入口,4核8G配置的CPU内存也会造成计算…

机器学习:BN层介绍及深入理解

前言:BN在深度网络训练过程中是非常好用的trick,在笔试中也很常考,而之前只是大概知道它的作用,很多细节并不清楚,因此希望用这篇文章彻底解决揭开BN的面纱。 BN层的由来与概念 讲解BN之前,我们需要了解B…

论文阅读-Pegasus:通过网络内一致性目录容忍分布式存储中的偏斜工作负载

论文名称:Pegasus: Tolerating Skewed Workloads in Distributed Storage with In-Network Coherence Directories 摘要 高性能分布式存储系统面临着由于偏斜和动态工作负载引起的负载不平衡的挑战。本文介绍了Pegasus,这是一个利用新一代可编程交换机…

CSP-动态规划-最长公共子序列(LCS)

一、动态规划 动态规划(Dynamic Programming,简称DP)主要用于求解可以被分解为相似子问题的复杂问题,特别是在优化问题上表现出色,如最短路径、最大子数组和、编辑距离等。动态规划的核心思想是将原问题分解为较小的子…

Microsoft Word 清除格式

Microsoft Word 清除格式 References 选择文本,用快捷键 Ctrl Shift N,可以快速清除格式。 选择文本,清除格式。 References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

CSS介绍

本章目标: CSS概述 三种样式表 简单选择器 复合选择器 盒子模型 常用背景样式 浮动 常用文本样式 伪类样式 列表样式 表格样式 定位 一、CSS概述: CSS:cascading style sheets-层叠样式表 专门负责对网页的美化 二、有三种使用方式&…

详解汉诺塔:递归树与纯函数编程

1. 汉诺塔问题为什么有解 相信只要接触过编程就会知道什么是汉诺塔问题: 有三根柱子,分别标记为A、B和C。初始时,在柱子A上按从大到小的顺序堆叠着若干个圆盘。目标是将所有的圆盘从柱子A移动到柱子C。在移动过程中可以借助柱子B作为辅助&a…