当前位置: 首页 > 面试题库 >

Python中的链式比较实际上如何工作?

严言
2023-03-14
问题内容

用于比较的Python文档说:

可以任意链接比较,例如x < y <= z与等效x < y and y <= z,不同之处在于y比较仅被评估一次(但在两种情况下zx < y被发现为假,则根本不评估)。

所以像(人为的例子):

if 1 < input("Value:") < 10: print "Is greater than 1 and less than 10"

只要求输入一次。这很有道理。和这个:

if 1 < input("Val1:") < 10 < input("Val2:") < 20: print "woo!"

仅询问Val2 是否 Val1介于1和10之间,并且仅打印“ woo!”。 if
Val2也在10到20之间(证明它们可以“任意链接”)。这也是有道理的。

但是我仍然很好奇在lexer / parser / compiler(或其他)级别上如何实际实现/解释这一点。

上面的第一个示例基本上是这样实现的:

x = input("Value:")
1 < x and x < 10: print "Is between 1 and 10"

x那些比较中真正存在的地方(实际上实际上是未命名的)?还是以某种方式使比较运算符同时返回布尔结果和正确操作数的评估(将用于进一步比较)还是类似的东西?

分析扩展到第二个示例会使我相信,它使用的是诸如未命名中间结果之类的东西(如果有一个术语,有人会教我),因为它在进行比较之前不会评估所有操作数。


问题答案:

您可以简单地让Python告诉您dis模块产生了什么字节码:

>>> import dis
>>> def f(): return 1 < input("Value:") < 10
... 
>>> dis.dis(f)
  1           0 LOAD_CONST               1 (1)
              3 LOAD_GLOBAL              0 (input)
              6 LOAD_CONST               2 ('Value:')
              9 CALL_FUNCTION            1
             12 DUP_TOP             
             13 ROT_THREE           
             14 COMPARE_OP               0 (<)
             17 JUMP_IF_FALSE_OR_POP    27
             20 LOAD_CONST               3 (10)
             23 COMPARE_OP               0 (<)
             26 RETURN_VALUE        
        >>   27 ROT_TWO             
             28 POP_TOP             
             29 RETURN_VALUE

Python使用堆栈;该CALL_FUNCTION字节码堆(上用途项目input的全球和'Value:'字符串)调用函数用一个参数,更换堆栈函数调用的结果在这两个项目。在函数调用之前,常量1已加载到堆栈中。

因此,在input被调用时,堆栈看起来像:

input_result
1

DUP_TOP复制最高值,然后旋转最高的三个堆栈值以得出:

1
input_result
input_result

COMPARE_OP用来测试前两项<,并用结果替换前两项。

如果结果是字节码跳转到27,FalseJUMP_IF_FALSE_OR_POP字节码将False顶部的剩余部分旋转到顶部,input_result用a清除该字节POP_TOP,然后返回剩余的False顶部值作为结果。

True但是,如果结果是该值,则该JUMP_IF_FALSE_OR_POP字节码会从堆栈中弹出该值,并将其放置10在顶部,我们得到:

10    
input_result

然后进行另一个比较并返回。

综上所述,基本上,Python会这样做:

stack_1 = stack_2 = input('Value:')
if 1 < stack_1:
    result = False
else:
    result = stack_2 < 10

stack_*值再次清除。

然后,堆栈保存 未命名的中间结果 以进行比较



 类似资料:
  • 我尝试在两个文件之间进行链式比较,如果结果在指定的时间间隔内,则打印/写出结果。 这就是我目前所拥有的。 test1文件: 测试2文件: 剧本本身: 我的首选输出是在test3中只包含以下行: 在第一列中有匹配的ID 第3列和第4列中的两个数值介于test1文件中给出的值之间 我没有得到输出,我不知道哪里出错了。

  • 我有这个代码: 我的IDE说:这看起来应该简化,即Python链式比较。 什么是链式比较,如何简化?

  • 问题内容: 我一直在阅读编程书,作者展示了一个类似的示例: 所以,我想知道为什么为什么等于假?如何比较这两个元组? 顺便说一句,这本书没有解释。 问题答案: 比较元组的位置:将第一元组的第一项与第二元组的第一项进行比较;如果它们不相等(即第一个大于或小于第二个),则这是比较的结果,否则将考虑第二个,然后是第三个,依此类推。 请参阅常见序列操作: 相同类型的序列也支持比较。特别是,通过比较相应的元素

  • 我正在用PyCharm编写一些python代码。当我编写以下测试时,它给了我一个警告。

  • 问题内容: 编译器或OS如何区分sig_atomic_t类型和普通的int类型变量,并确保操作是原子的?两者都使用的程序具有相同的汇编代码。如何特别注意使操作原子化? 问题答案: 不是原子数据类型。仅仅是允许您在信号处理程序的上下文中使用的数据类型,仅此而已。因此最好将其名称理解为“相对于信号处理而言是原子的”。 为了保证与信号处理程序之间的通信,仅需要原子数据类型的属性之一,即读取和更新将始终看

  • 问题内容: 我有一个Applet,它使用URLConnection通过HTTP连接加载图像。我正在为所有连接设置setUseCaches(true),但仍然看不到任何缓存行为。我图像的HTTP标头具有合理的缓存设置。如果您查看错误4528599,则有一个相当神秘的陈述: Java插件的当前版本(1.3.1)仅检查浏览器缓存中名称以.jar或.class结尾的文件。我被告知,对于Java Plug-