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.mzph.cn/news/681885.shtml

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

相关文章

2024年,要特别注意这两个方位

家居风水对每个家庭都非常重要,可在无形中影响到人们的事业、财富以及健康运势。俗话说:“风水轮流转”,2024年为甲辰龙年,斗转星移、九宫飞星将改变宫位,新一年的磁场即将启动,方位的吉凶也会重新变动&…

oracle单机打DBBP补丁

书接上回 ORA-600 adg无法查询故障-CSDN博客 https://blog.csdn.net/q195136130/article/details/135445378?spm1001.2014.3001.5502 单机安装DBBP 解压缩补丁包 unzip p34204559_121020_Linux-x86-64.zip 关闭数据库 su - oraclesqlplus / as sysdbashut immediate 检查…

Mac上软件闪退(意外退出)的解决方法

mac苹果电脑上运行软件会意外退出,怎么办,可以试试下面的方法,亲测可行! 第一种方法: 1、打开访达,进入应用程序目录,找到闪退的软件图标,在软件图标上右键选择“显示简介”&#…

OpenCV 人脸检测(易上手版)

在丰富多彩的计算机视觉世界中,人脸检测是最有趣和最广泛应用的领域之一。无论是在安全系统、用户界面控制,还是在社交媒体中应用过滤器,准确有效地检测人脸的能力都是至关重要的。今天,很高兴与大家分享如何在 Python 中使用 Ope…

【网络攻防实验】【北京航空航天大学】【实验三、口令破解(Password Cracking)实验】

实验三、口令破解(Password Cracking)实验 一、 L0phtCrack破解实验 1、 注册L0phtCrack: 2、 设置口令: (1) 创建3个新账户: 帐户创建过程(以test-1为例): 帐户创建结果: (2) 使用L0phtCrack破解口令:(使用管理员账号运行程序) 口令破解结果: 正确破解口令…

探讨深度学习

深度学习 深度学习概述进展崛起框架 主页传送门:📀 传送 深度学习 概述 深度学习是机器学习领域的一个分支,它是一种基于人工神经网络的学习方法,旨在让 计算机模仿人类大脑的神经结构和学习方式,从大量数据中学习并…

代码随想录算法训练营Day25|回溯算法·组合总和III,电话号码的字母组合

组合总和III 题目:找出所有相加之和为n的k个数的组合。组合中只允许含有1-9的正整数,并且每种组合中不存在重复的数字。 组合变量个数为k个,和为n。简单思路是使用k重循环,一层层找出来,然后把每一层的数相加&#x…

操作系统——1.1 操作系统的基本概念1.2 操作系统发展历程

参考课程是王道上传到b站的操作系统,主讲老师是咸鱼,相关的截图都是课程内的,阅读前建议大家支持王道的正版课程。 第一章 计算机系统概述 1.1 操作系统的基本概念&1.2 操作系统发展历程 一、概念 操作系统的概念 操作系统的功能和目…

学习总结11

KMP算法 全称Knuth-Morris-Pratt算法,是一种字符串匹配算法。该算法的目的是在一个文本串S内查找一个模式串P的出现位置。 KMP算法的核心思想是利用模式串自身的特性来避免不必要的字符比较。算法通过构建一个部分匹配表(也称为next数组)&a…

概率在AI中的应用

更多AI技术入门知识与工具使用请看下面链接: https://student-api.iyincaishijiao.com/t/iNSVmUE8/

VUE学习——表单的输入绑定

使用【v-model】。 输入框 <template><h1>表单输入绑定</h1><input type"text" v-model"message"><p>输入的值&#xff1a;{{ message }}</p> </template> <script>export default{data(){return{messa…

快速的搭建一个临时的 Linux 系统instantbox

centos 安装 docker-CSDN博客 首先要有docker && docker-compose mkdir instantbox && cd $_ bash <(curl -sSL https://raw.githubusercontent.com/instantbox/instantbox/master/init.sh) docker-compose up -d instantbox: instantbox 可以让你快速的搭…

黑马程序员——移动Web——day01

目录&#xff1a; 平面转换 简介平移定位居中案例-双开门旋转转换原点案例-时钟多重转换缩放案例-播放特效倾斜渐变 线性渐变案例-产品展示径向渐变综合案例 导航-频道渐变按钮轮播图猜你喜欢 1.平面转换 简介 作用&#xff1a;为元素添加动态效果&#xff0c;一般与过渡配…

GEE重投影——NICFI数据集重投影到WGS84坐标

简介 重投影 遥感影像的重投影是将一幅影像从一个地理坐标系统转换到另一个地理坐标系统的过程。在遥感应用中,重投影非常重要,因为不同的遥感影像可能来自于不同的遥感传感器或不同的地理坐标系统,而在进行数据分析和集成时,需要保证所有影像在同一地理坐标系统下。 重…

(二)【Jmeter】专栏实战项目靶场drupal部署

该专栏后续实战示例&#xff0c;都以该篇部署的项目展开操作。 前置条件 参考“&#xff08;一&#xff09;【Jmeter】JDK及Jmeter的安装部署及简单配置” 安装部署Jmeter&#xff0c;从文章最后下载“Postman、Rancher.ova、VirtualBox-7.0.12-159484-Win.exe、Xshell-7.0.01…

小白学习Halcon100例:如何利用动态阈值分割图像进行PCB印刷缺陷检测?

文章目录 *读入图片*关闭所有窗口*获取图片尺寸*根据图片尺寸打开一个窗口*在窗口中显示图片* 缺陷检测开始 ...*1.开运算 使用选定的遮罩执行灰度值开运算。*2.闭运算 使用选定的遮罩执行灰度值关闭运算*3.动态阈值分割 使用局部阈值分割图像显示结果*显示原图*设置颜色为红色…

ARMv8-AArch64 的异常处理模型详解之异常处理概述Handling exceptions

异常处理模型详解之异常处理概述 一&#xff0c;异常处理相关概念二&#xff0c;异常处理概述 一&#xff0c;异常处理相关概念 在介绍异常处理之前&#xff0c;有必要了解一些关于异常处理状态的术语&#xff1a; 当处理器响应一个异常时&#xff0c;我们称该异常被获取了&a…

PIL Image 使用详解

文章目录 1. 各种图像处理库介绍1.1 读取数据的通道顺序1.2 Python图像处理库&#xff08;PIL、Pillow、Scikit-image、Opencv&#xff09; 2、PIL库与Pillow库的区别3 Pillow库3.1 Pillow库特点3.2 Pillow库安装 4、Pillow的Image对象&#xff08;PIL.Image&#xff09;4.1 Im…

Peter算法小课堂—区间模型(2)

上次咋们讲了前两个区间模型&#xff1a;1.最大不重叠区间数 2.不重叠区间最少分组数。今天我们就学习&#xff1a;最小区间覆盖问题、区间重叠最厚层数&#xff01; 最小区间覆盖 先看三道题 那么&#xff0c;第1题&#xff0c;它是浮点数的题&#xff0c;也就要求首尾相同。…

知识图谱 多模态学习 2024 最新综述

知识图谱遇见多模态学习&#xff1a;综述 论文题目&#xff1a;Knowledge Graphs Meet Multi-Modal Learning: A Comprehensive Survey 论文链接&#xff1a;http://arxiv.org/abs/2402.05391 项目地址&#xff1a;https://github.com/zjukg/KG-MM-Survey 备注&#xff1a;55…