CPython:比较运算符串联的差异

相关阅读

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


        在C语言和Python中,比较运算符是一个常用的运算符,但这两种语言在某些情况下对比较运算符的解析缺存在差异,本文旨在明确这一点。

Python中的比较运算符串联

        首先来看Python官方文档中对比较运算符的定义,下面是定义的BNF范式。

comparison    ::=  or_expr (comp_operator or_expr)*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "!="| "is" ["not"] | ["not"] "in"

        BNF显示比较运算的构成是至少一个or_expr表达式和若干个comp_operator运算符、or_expr的组合,本文我们可以简单地把or_expr表达式当做一个常数。其中comp_operator可以是下面三类中的符号。

  •         值比较:小于(<)、大于(>)、等于(==)、大于等于(>=)、小于等于(<=)、不等于(!=)
  •         标识号比较:是(is)、不是(is not)
  •         成员检测:在...内(in)、不在...内(not in)。

        本文只讨论值比较(因为C没有标识号和成员检测比较符),但结论适用于所有比较符。在编程中,我们常常会需要比较三者之间的关系,例如A==B==C,又或者A>B>C...,在Python中,这很好实现,因为Python将多个串联的比较运算符看作是两两组合,并且通过“布尔与”运算符连接。

        比如,在Python中,表达式A>B>C几乎等价于A>B and B>C,唯一的差别在于:后一种写法中,子表达式B会被求值两次,而在第一种写法中,子表达式B只会被求值一次(注意:在两种写法中,当A>B为真时,C表达式不会再被求值,这被称作逻辑短路)。

        上面的描述也许不够直观,下面来看几个例子加深理解。

例1
print(5>4>3)
Ture

        根据上面的解析规则,例1所示的表达式被近似解析为图1所示的语法分析树。

图1 语法分析树

        例2展示了,表达式A>B>C和表达式A>B and B>C之间的细微差别,为了体现求值顺序,我们定义了三个函数,函数内会打印信息,并将其作为比较表达式的子表达式。

例2
def func5():print("This is 5")return 5def func4():print("This is 4")return 4def func3():print("This is 3")return 3print(func5() > func4() > func3())
This is 5
This is 4
This is 3
Trueprint(func5() > func4() and func4() > func3())
This is 5
This is 4
This is 4     #func4()被求值两次
This is 3
True

        该例不仅展示了func4()函数在两种表达式中的求值次数不同,还侧面验证了之前的文章中说的:Python的求值顺序是从左到右的C&Python:表达式的求值顺序(evaluation order)。

        下面的例3展示了比较运算符的逻辑短路性质,需要注意的是:这实际上是由“布尔与”运算符带来的性质。

例3
def func5():print("This is 5")return 5def func4():print("This is 4")return 4def func3():print("This is 3")return 3print(func5() < func4() < func3())
This is 5
This is 4    #func3()不求值
Falseprint(func5() < func4() and func4() < func3())
This is 5
This is 4    #func3()不求值
False

C语言中的比较运算符串联

        在使用C语言中的比较运算符时需要更加谨慎,图2是C11中比较运算符的语法。

图2 C11中比较运算符的语法

        可以从图2中总结出比较运算表达式从左向右的结合性,即一个比较表达式可以作为一个子表达式称为另一个比较表达式的左操作数,而不是右操作数。举例来说,表达式A>B>C在C语言中会被解析为子表达式A先与子表达式B比较,比较结果再与子表达式C比较,而这不是一般情况下我们想要的比较方式,即A大于B大于C。

        下面我们来看一个例子,具体说明上面的描述。

例4
#include <stdio.h>
int main()
{printf("The result of expression is %d",5>4>3);
}The result of expression is 0

        根据上面的解析规则,例4所示的表达式被近似解析为图3所示的语法分析树。 

图3 语法分析树

        那么该如何实现A大于B大于C这种比较呢?其实只用像Python一样,直接显式使用“逻辑与”运算符连接多个比较表达式就可以了,如例4所示。

​例4
#include <stdio.h>
int main()
{printf("The result of expression is %d",5>4 && 4>3);
}The result of expression is 1

        最后顺带一提,C语言也和Python一样拥有逻辑短路性质,即使之前的文章说过,C语言不保证很多表达式的求值顺序,但对于几个特殊的表达式规定了求值顺序,其中就包含“逻辑与”运算符:首先求值&&的左操作数,再求值&&的右操作数,并且拥有逻辑短路性质,下面举例说明。

例5
#include <stdio.h>
int func5()
{printf("This is 5\n");return 5;
}int func4()
{printf("This is 4\n");return 4;
}int func3()
{printf("This is 3\n");return 3;
}int main()
{printf("The result of expression is %d",func5()<func4() && func4()>func3());
}This is 5
This is 4    //func3没有被求值
The result of expression is 0

 

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

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

相关文章

正则表达式应用

应用一&#xff1a;去掉特殊的行&#xff0c;保留想要的行 文档中包含如下内容&#xff1a; 去掉特殊的行&#xff0c;只保留图像名的行。"0.\d{1,2}" ^\s*$\r\n去除后结果 去除没有内容的行 去除结果 总结

LeetCode Python - 31.下一个排列

目录 题目答案运行结果 题目 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更…

LL-34/DO-213AC/MiniMELF/NSMC/DO-213AB封装

最近在找几个特殊的二极管封装&#xff0c;能查到资料太少了&#xff0c;如同大海捞针&#xff0c;好不容易找到了一些资料&#xff0c;把相关信息总结一下. 1、LL-34/DO-213AC/MiniMELF/SOD80这三个封装尺寸很接近 LL-34以c5345992为例 MiniMELF以c131658为例 2、NSMC这个封装…

学习python时一些笔记

1、winr 命令提示符的快捷键 输入cmd进入终端 2、在终端运行桌面上的python文件 cd desktop(桌面) cd是进入该文件夹的意思。 cd .. 回到上一级 运行python时一定要找到文件的所在地 输入python进入&#xff0c;exit()退出%s字符串占位符%d数字占位符%f浮点数占位符input输…

理解CAE

用于自监督表示学习的上下文自动编码器 摘要 我们提出了一种新的掩模图像建模(MIM)方法&#xff0c;上下文自编码器(CAE)&#xff0c;用于自监督表示预训练。我们通过在编码的表示空间中进行预测来预训练编码器。预训练任务包括两个任务:掩模表示预测—预测掩模块的表示&…

Cannot resolve plugin org.apache.maven.plugins:maven-resources-plugin:3.3.0

问题现象&#xff1a; Cannot resolve plugin org.apache.maven.plugins:maven-resources-plugin:3.3.0 Try to run Maven import with -U flag (force update snapshots) Cannot resolve plugin org.apache.maven.plugins:maven-resources-plugin:3.3.0是因为配置的maven仓库…

网络编程:基于TCP和UDP的服务器、客户端

1.基于TCP通信服务器 程序代码&#xff1a; 1 #include<myhead.h>2 #define SER_IP "192.168.126.121"//服务器IP3 #define SER_PORT 8888//服务器端口号4 int main(int argc, const char *argv[])5 {6 //1.创建用于监听的套接字7 int sfd-1;8 sf…

AJAX 学习笔记(Day3)

「写在前面」 本文为黑马程序员 AJAX 教程的学习笔记。本着自己学习、分享他人的态度&#xff0c;分享学习笔记&#xff0c;希望能对大家有所帮助。推荐先按顺序阅读往期内容&#xff1a; 1. AJAX 学习笔记&#xff08;Day1&#xff09; 目录 3 AJAX 原理 3.1 XMLHttpRequest 3…

记一次:android学习笔记一(学习目录-不要看无内容)

学习目录如下 B站学习的名称--Android开发从入门到精通(项目案例版) 网址:https://www.bilibili.com/video/BV1jW411375J/ 第0章:安装 android stoid 参考地址https://blog.csdn.net/adminstate/article/details/130542368 第一章:第一个安卓应用 第二章:用户界面设…

微信小程序-生命周期

页面生命周期 onLoad: 页面加载时触发的方法&#xff0c;在这个方法中可以进行页面初始化的操作&#xff0c;如获取数据、设置页面状态等。 onShow: 页面显示时触发的方法&#xff0c;在用户进入页面或从其他页面返回该页面时会调用此方法。可以在此方法中进行页面数据刷新、动…

迅为LS2K0500开发板邮票孔方式连接,CPU全部功能引出脚155个

CPU&#xff0c;迅为LS2K0500开发板采用龙芯2K0500处理器&#xff0c;基于龙芯自主指令系统 (LoongArch) 架构&#xff0c;片内集成64位LA264处理器核。实现ACPI、DVFS/DPM动态电源功耗管理等低功耗技术&#xff0c;支持多种电源级别和唤醒方式&#xff0c;可根据具体应用场景对…

C++11线程同步之互斥锁

C11线程同步之互斥锁 std::mutex成员函数线程同步 std::lock_guardstd::recursive_mutexstd::timed_mutex 进行多线程编程&#xff0c;如果多个线程需要对同一块内存进行操作&#xff0c;比如&#xff1a;同时读、同时写、同时读写对于后两种情况来说&#xff0c;如果不做任何的…