<p>Python不需要转换任何东西,如果愿意的话也不能转换。在</p>
<p>使用<a href="https://docs.python.org/3/reference/grammar.html" rel="noreferrer">language grammar</a>将条件表达式解析为<a href="https://docs.python.org/3/library/ast.html" rel="noreferrer">abstract syntax tree</a>,然后将其编译为字节码。您可以使用<a href="https://docs.python.org/3/library/ast.html#ast.parse" rel="noreferrer">^{<cd1>} function</a>生成AST:</p>
<pre><code>>>> import ast
>>> ast.parse('c = a if condition else b').body[0] # first statement in the tree
<_ast.Assign object at 0x10f05c550>
>>> ast.dump(ast.parse('c = a if condition else b').body[0])
"Assign(targets=[Name(id='c', ctx=Store())], value=IfExp(test=Name(id='condition', ctx=Load()), body=Name(id='a', ctx=Load()), orelse=Name(id='b', ctx=Load())))"
</code></pre>
<p>注意AST中为赋值生成的<code>ast.IfExp()</code>节点;这是用于条件表达式的专用节点。它有<code>test</code>、<code>body</code>和<code>orelse</code>部分来表示构成条件的3个表达式,真和假部分。这在<a href="https://docs.python.org/3/library/ast.html#abstract-grammar" rel="noreferrer">^{<cd6>} module <em>Abstract Grammar</em> section</a>中有记录:</p>
<blockquote>
<pre><code>expr = [...]
| [...]
| IfExp(expr test, expr body, expr orelse)
</code></pre>
</blockquote>
<p>这表明每个元素的类型是另一个<code>expr</code>表达式节点。在</p>
<p>然后将解析树编译为字节码,该字节码使用堆栈根据测试有条件地跳转到右边的部分;我们可以将<code>ast.parse()</code>生成的AST直接传递给<a href="https://docs.python.org/3/library/functions.html#compile" rel="noreferrer">^{<cd9>} function</a>,之后,<a href="https://docs.python.org/3/library/dis.html" rel="noreferrer">^{<cd10>} module</a>让我们查看编译生成的字节码的友好形式:</p>
^{pr2}$
<p>因此,如果条件为false,解释器循环向前跳到指令8,否则执行指令4和指令6,指令6跳到指令10(因此超过<code>else</code>表达式)。最终结果是,指令4或指令8将一个新结果放在堆栈顶部,<code>STORE_NAME</code>移动到变量。在</p>
<p>一个<code>if</code>语句会导致一个不同的AST节点,而产生的字节码<em>恰好</em>非常相似,因为它也会使用跳转。但是编译器将它们视为不同的语法片段,并且<em>有</em>to。在</p>
<p>表达式和语句是编程语言的两个非常不同的基本构造块。语句可以包含表达式,但表达式不能包含语句,只能包含其他表达式。和表达式可以生成一个值(供周围的语法使用),但语句<em>不能</em>。因此Python必须将条件表达式与语句处理得非常不同,因为语法解析器知道何时需要语句以及何时允许使用表达式。如果你把一个条件表达式转换成一个语句,你将永远不能使用这样的表达式作为一个更大的表达式的一部分!在</p>
<p>因为<code>if</code>语句不是表达式</em>,它不会返回值(因为只有表达式才能产生值),因此生成的字节码不会在堆栈顶部生成一个值供周围的Python代码使用(没有<code>c = if condition : ...</code>)。<code>if</code>语句包含一个<em>条件表达式</em>和一个<em>suite</em>,这两个语句必须总是由更多的语句组成(有一个“expression statement”这样的东西可以让您在一个语句中只放一个表达式,例如<code>1 + 1</code>),这些语句可以“执行诸如赋值或从函数返回之类的事情,但是他们做的任何事都不会让<code>if</code>返回一些东西。在</p>
<p>这反映在<code>if</code>语句的AST节点定义中:</p>
<blockquote>
<pre><code>stmt = [...]
| [...]
| If(expr test, stmt* body, stmt* orelse)
</code></pre>
</blockquote>
<p>因此对于一个<code>If</code>节点,<code>test</code>是唯一的表达式节点,<code>body</code>和{<cd5>}都由零个或多个</em>语句组成。<code>orelse</code>部分将包含任何<code>elif ...:</code>测试作为进一步的<code>If()</code>节点,或任何其他类型的语句来形成一个无条件的<code>else:</code>。对于零个或多个元素,您不能期望一个单独的结果。在</p>
<p>所以这并不是CPython独有的,它适用于所有Python实现。Python<em>语法</em>不是实现细节。在</p>