11

Python の 3 項条件の両側でステートメントを使用することが禁止されているのはなぜですか? 以下の単純な構文の例のいくつかがあいまいまたは壊れている可能性がある明確な理由はわかりませんが、それが許可されていないのには十分な理由があるに違いありません!

>>> x, y = 0, 0
>>> (x += 1) if random.choice([0, 1]) else (y += 1)
        ^
SyntaxError: invalid syntax

>>> (x if random.choice([0, 1]) else y) += 1
SyntaxError: can't assign to conditional expression


>>> print 'hello world' if random.choice([0, 1]) else raise StandardError()
  File "<stdin>", line 1
    print 'hello world' if random.choice([0, 1]) else raise StandardError()
                                                          ^
SyntaxError: invalid syntax

ステートメントを 3 項で使用できるようにすることが危険または不明確になる可能性がある例を挙げていただけますか?

4

4 に答える 4

7

表現がeval使われ、ステートメントがexec使われます。これはまったく違うものです。

Python 開発者は、式とステートメントを厳密に分離することを決定しました。これにより、デバッグが困難なエラーが発生するのではなく、「早期に失敗」します。

C(++) などの他の言語では、次のようなことができます。

if (i=15) {...}

しかし、あなたもできる

if (i==15) {...}

最初の例では、変数 に 15 を割り当てi、 のこの新しい値がiによって評価されますif

さらに悪いのは、インクリメント/デクリメント演算子です。違いは何ですか

if (i--) {...}

if (--i) {...}

?

最初の例では、 の値iが評価され、インクリメントされます。2 番目の例では、順序が逆であるため、前にあった場合i1結果が異なります。

Python では、他の言語でそのような概念を収集した経験があるため、そのようなことは構文によって禁止されています。

これがあなたの質問に完全に答えるかどうかはよくわかりませんが、少なくともpythonicアプローチについての洞察を与えることができれば幸いです.

于 2013-01-23T07:13:59.863 に答える
4

これは条件式1とは関係ありません。Python プログラムはステートメントで構成されています。ほとんどのステートメントのほとんどの部分は式です。式には他の式のみが含まれます。

y += 1はステートメントであり、式が期待される場所では使用できません。三項条件は全体として式であり、その 3 つの部分のそれぞれが式です。(x += 1) if random.choice([0, 1]) else (y += 1)次の怪物を許可する以上に、許可する理由はありません。

x = (y += 1)
def foo(x=(x += 1)):
    print x
print [x += 1, x *= 10]

式は、何らかの値に評価できるものです。ステートメントは値を持たないものです。ステートメントを条件式の「true の場合」または「false の場合」オペランドとして許可する場合、どの式でもどのステートメントも許可しないのはなぜですか? 結局、それは文法を複雑にして、ステートメントを含むことができる唯一の種類の式が条件式になるようにします。

x = y + pass
[return True, import sys]

これらはどれも意味がありません。(x += 1) if random.choice([0, 1]) else (y += 1)条件式の要点は式であるためです。したがって、次のようなステートメントでより現実的に表示されます。

z = (x += 1) if random.choice([0, 1]) else (y += 1)

x += 1Cのように、の「値」がx(1が追加される前または後のいずれかの)の値であるという規則が考えられます。しかし、それは言語をかなり複雑にします。それでも、次の問題は解決しません。

z = pass if (import sys) else (while False: print 17)

の値はpass? のimport sys? whileループの?

これを機能させるには、Python の文法に存在するクラスとしての「ステートメント」を「表現ステートメント」と「通常のステートメント」に分離するか、特定の種類のステートメントの値について任意のルールを考案する必要があります。それは。おそらく両方。

単純な事実は、これを単一のステートメントとして記述しようとしている場合です。

(x += 1) if random.choice([0, 1]) else (y += 1)

次に、Python にはこのアイデアを表現するための構文が既にあり、それは次のとおりです。

if random.choice([0, 1]):
    x += 1
else:
    y += 1

ifステートメントを条件式 (値は無視される) として記述してステートメントを難読化できるようにするためだけに、ステートメントを式のコンポーネントとして配置する言語 (および読みやすさ) に複雑さを導入する必要はありません。


1必要に応じて「三項条件」と呼んでください。ただし、「三項」または「三項演算子」は単にばかげています。オペランドが 3 つあるということは、最も重要なことではありません。+それは「二項演算子」を呼び出すようなものです。

于 2013-01-23T07:43:58.033 に答える
1

最初の構文

最初の構文は実際には従来のif ステートメントであり、条件と最初のアクションを逆にして1行で書き込もうとしました。このように1行の構成を使用するのはやり過ぎであり、醜くて読みにくいです。PythonはCではありません。

2番目の構文

Pythonの条件式の結果はではないため、2番目の構文は機能しませrvaluelvalue(リンクはCとMicrosoftについて説明していますが、これはすべての言語で発生する一般的な用語です)。rvalueは式であり、代入の右側でのみ発生する可能性があります。lvalueただし、右側または左側のいずれかで発生する可能性があります。lvalueが右側にある場合は、左側にあるものの評価に使用された値です。lvalueが左側にある場合、そのアドレスは、評価後の右側の式の値を格納するために使用されます。

Pythonでは、すべてが参照であり、参照が指すlvalueものを変更できますが、できません。rvalue

例:

a = 5 # here a is lvalue
b = a + 1 # here a is rvalue and b is lvalue

-only式のもう1つの例は、rvalue定数です。通訳者の観点からすると、2回目の試行は次のようになります。

42 = 42 + 1 # WHAT THE HECK!?

なぜ

条件式をステートメントなしにすることが決定された理由については(おっと、すでに理由がわかっているようです!):PEP 308が述べているように、条件式は最初、エラーが発生しやすいx and y or zブール式の代わりに使用するために導入されました。短絡評価のため、同じように機能しました。

Pythonが条件文であなたのようなステートメントを許可する場合、たとえば、を許可する必要がありましたraise。ワンライナーに多くのロジックを詰め込むことは悪いPythonコードスタイルと見なされます(私が上で言ったように)。

これを見てください

result = some_long_name / some_other_name if some_other_name != 0 else raise ZeroDivisionError

最初は式のように見えますが、ステートメントのように動作し、例外を発生させることさえあります。:( 79文字で行を削除するというPythonの推奨事項を念頭に置くとraise、たとえば、マルチウィンドウを並べて表示することすらできません。


于 2013-01-23T08:51:28.660 に答える
-4

使用しているpythonのバージョンは何ですか?この構文は、少なくとも python 2.4 ではサポートされていません。以下は python 3.3 で機能しました。補足として、括弧を削除します。

import random
x,y=0,0
x += 1 if random.choice([0,1]) else (y +1)
于 2013-01-23T07:10:26.847 に答える