我知道条件表达式(或三元运算符)在Python中是懒惰的。它们表示条件执行而不是条件选择。换言之,只有a
或{
c = a if condition else b
我感兴趣的是这是如何在内部实现的。Python是否像下面这样转换为if
语句,如果是,转换发生在什么阶段?在
或者三元运算符实际上是一个完全独立定义的独立表达式?如果是,我可以访问条件表达式的CPython代码吗?在
我已经看了下面这些解释了三元运算符的作用,但没有一个清楚地说明它们是如何实现的:
编辑:您可以假设CPython引用实现。在
差不多了。在
该输出:
^{pr2}$除了}之外,这些看起来几乎相同。在
JUMP_FORWARD
的位置和@L3viathan指出的另外一个{我们也得到了几乎相同的执行时间(差别微乎其微):
至于当发生这种转换时,我假设在“编译”到字节码的某个时候。在
什么
如果你在问什么,那么为了更好地理解它,你需要理解功能和程序之间的区别。一个可以转换为另一个,但两个都可以独立查看,您不必将其中一个转换为另一个才能理解它们。在
value_a if condition else value_b
是函数型的,返回值value_a
或{是程序性的,它执行}。在
do_a
或{注意:程序就是做,做这个,然后做那个,或者那个。功能是关于价值的,是这个还是那个。在
怎么回事
如果你在问怎么做,那么你需要看看其中一个实现的源代码。请注意,只要行为正确,每个实现不必以相同的方式执行。在
Python不需要转换任何东西,如果愿意的话也不能转换。在
使用language grammar将条件表达式解析为abstract syntax tree,然后将其编译为字节码。您可以使用^{} function 生成AST:
注意AST中为赋值生成的} module Abstract Grammar section 中有记录:
ast.IfExp()
节点;这是用于条件表达式的专用节点。它有test
、body
和orelse
部分来表示构成条件的3个表达式,真和假部分。这在^{这表明每个元素的类型是另一个
expr
表达式节点。在然后将解析树编译为字节码,该字节码使用堆栈根据测试有条件地跳转到右边的部分;我们可以将} function ,之后,^{} module 让我们查看编译生成的字节码的友好形式:
^{pr2}$ast.parse()
生成的AST直接传递给^{因此,如果条件为false,解释器循环向前跳到指令8,否则执行指令4和指令6,指令6跳到指令10(因此超过
else
表达式)。最终结果是,指令4或指令8将一个新结果放在堆栈顶部,STORE_NAME
移动到变量。在一个
if
语句会导致一个不同的AST节点,而产生的字节码恰好非常相似,因为它也会使用跳转。但是编译器将它们视为不同的语法片段,并且有to。在表达式和语句是编程语言的两个非常不同的基本构造块。语句可以包含表达式,但表达式不能包含语句,只能包含其他表达式。和表达式可以生成一个值(供周围的语法使用),但语句不能。因此Python必须将条件表达式与语句处理得非常不同,因为语法解析器知道何时需要语句以及何时允许使用表达式。如果你把一个条件表达式转换成一个语句,你将永远不能使用这样的表达式作为一个更大的表达式的一部分!在
因为
if
语句不是表达式,它不会返回值(因为只有表达式才能产生值),因此生成的字节码不会在堆栈顶部生成一个值供周围的Python代码使用(没有c = if condition : ...
)。if
语句包含一个条件表达式和一个suite,这两个语句必须总是由更多的语句组成(有一个“expression statement”这样的东西可以让您在一个语句中只放一个表达式,例如1 + 1
),这些语句可以“执行诸如赋值或从函数返回之类的事情,但是他们做的任何事都不会让if
返回一些东西。在这反映在
if
语句的AST节点定义中:因此对于一个}都由零个或多个语句组成。
If
节点,test
是唯一的表达式节点,body
和{orelse
部分将包含任何elif ...:
测试作为进一步的If()
节点,或任何其他类型的语句来形成一个无条件的else:
。对于零个或多个元素,您不能期望一个单独的结果。在所以这并不是CPython独有的,它适用于所有Python实现。Python语法不是实现细节。在
相关问题 更多 >
编程相关推荐