当前位置: 首页 > 后端技术 > Python

Python随笔(二):链式比较运算

时间:2023-03-26 00:27:05 Python

0。前言Python中的链式比较操作(chainedcomparisons)是其他语言很少实现的特性之一。本文将对这个特性进行一些研究。本文中Python解释器版本:Python3.8.0(tags/v3.8.0:fa919fd,Oct142019,19:21:23)[MSCv.191632bit(Intel)]onwin32(CPython)1。问题描述代码段如下:defis_ascending_simple(a:int,b:int,c:int)->bool:returnabool:returna>>>>>defis_ascending_simple(a:int,b:int,c:int)->bool:...returna>>>>>defis_ascending_chained(a:int,b:int,c:int)->bool:...returna>>>>>print("is_ascending_simple(1,2,3):{}".format(is_ascending_simple(1,2,3)))is_ascending_simple(1,2,3):True>>>print("is_ascending_simple(1,3,2):{}".format(is_ascending_simple(1,3,2)))is_ascending_simple(1,3,2):False>>>print("is_ascending_chained(1,2,3):{}".format(is_ascending_chained(1,2,3))))is_ascending_chained(1,2,3):True>>>print("is_ascending_chained(1,3,2):{}".format(is_ascending_chained(1,3,2)))is_ascending_chained(1,3,2):False>>>那么,表达式aaop1bandbop2cand...yopNz之后,但每个子表达式最多求值一次。下面我们举例说明研究定义中的描述。2.1.验证等价性请参考“1.问题描述”一节。2.2.验证代码最多被评估一次:#chaining-comp-2-2.pydefget_number_log(n:int)->int:"""按原样返回一个数字并将请求的数字记录到终端。"""print("get_number_log(n)调用n={}".format(n))returnnprint("Simplecomp:{}".format(get_number_log(1)py-3.\chaining-comp-2-2.pyget_number_log(n)调用n=1get_number_log(n)调用n=2get_number_log(n)调用n=2get_number_log(n)调用n=3Simplecomp:Trueget_number_log(n)调用n=1get_number_log(n)调用n=2get_number_log(n)calledwithn=3Chainedcomp:TruePS>原理:使用get_number_log()函数记录每个表达式的求值。结论:从两次表达式求值中get_number_log()求值次数的不同,原命题得证。2.3.验证短路2.3.1。判断短路表达式是否执行代码:#chaining-comp-2-3-1.pyclassMyInt:"""一个类似于int的用户定义类。每次self.__lt__()调用都会被记录下来。"""def__init__(self,n:int):self._n=ndef__lt__(self,another)->bool:print("MyInt.__lt__()调用self={}another={}".format(self._n,another._n))returnself._npy-3.\chaining-comp-2-3-1.pyMyInt.__lt__()calledwithself=1another=2MyInt.__lt__()calledwithself=2another=3my_one原理:使用自定义类和__lt__()特殊函数来记录bool:return(SENTRY_RET_VALifanother._n==SENTRYelseself._npy-3.\chaining-comp-2-3-2.pymy_one原理:按照2.3.1节同样的方法自定义__lt__()特殊函数。当第二个操作数是SENTRY时,返回SENTRY_RET_VAL而不是正常的布尔值,以检测链式比较操作是否具有Python3.8References6.11中描述的一般布尔操作行为。布尔运算。结论:观察返回SENTRY_RET_VAL,原命题得证。2.4.CPython字节码中的证据CPython字节码(bytecode)是CPython对已解析的Python源代码(source)的内部表示。CPython字节码的具体内容与CPython实现细节(CPythonimplementationdetail)有关,所以不存在跨平台。通过字节码,用户可以从执行的底层观察代码的解析。Python内置电池中的dis模块(此处为文档)允许用户在运行时检查已解析函数的字节码实现。代码:defis_ascending_simple(a:int,b:int,c:int)->bool:returnabool:returna>>>>>defis_ascending_simple(a:int,b:int,c:int)->bool:...returna>>>>>defis_ascending_chained(a:int,b:int,c:int)->bool:...returna>>>>>importdis>>>dis.dis(is_ascending_simple)20LOAD_FAST0(a)2LOAD_FAST1(b)4COMPARE_OP0(<)6JUMP_IF_FALSE_OR_POP148LOAD_FAST1(b)10LOAD_FAST2(c)12COMPARE_OP0(<)>>14RETURN_VALUE>>>dis.dis(is_ascending_chained)20LOAD_FAST0(a)2LOAD_FAST1(b)4DUP_TOP6ROT_THREE8COMPARE_OP0(<)10JUMP_IF_FALSE_OR_POP1812LOAD_FAST2(c)14COMPARE_OP0(<)16RETURN_VALUE>>18ROT_TWO_VALUE202POPRN_TOPVALUE202POPRN_TOPVALUE>>>is_ascending_simple()的字节码比较简单,不再赘述。下面简单分析一下is_ascending_chained()的运行栈。下面分析抽象的格式如下:LineNo(("b"DescriptionOfBranch)|(["y""n"]))?(“返回(“RetVal”)”)?(“堆栈(“StackDescription”)”)?2Stack(BottomabTop)4Stack(BottomabbTop)6Stack(BottombabTop)8ba