if-elif-elseステートメントを1行に記述しますか?


123

以下のリンクを読みましたが、私の質問には対応していません。
Pythonには三項条件演算子がありますか?(問題はif-elseステートメントを1行に圧縮することです)

1行に収まるようにif-elif-elseステートメントを書く簡単な方法はありますか?
例えば、

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

または実際の例:

if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

上記の例を次のように書くと、もっと簡潔に見えるかもしれません。

x=2 if i>100 elif i<100 1 else 0 [WRONG]

回答:


183

いいえ、それは不可能です(少なくとも任意のステートメントでは不可能です)ことも、望ましいことでもありません。すべてを1行に収めると、PEP-8に違反する可能性が高くなります。この場合、行の長さが80文字を超えないようにする必要があります。

これは、Zen of Pythonの「読みやすさを重視」にも反対しています。(import this全体を読むには、Pythonプロンプトで入力します)。

あなたはできるだけの表現のためではなく、文のために、Pythonで三項の式を使用します。

>>> a = "Hello" if foo() else "Goodbye"

編集:

変更後の質問では、割り当てられている値を除いて、3つのステートメントが同じであることが示されています。その場合、連鎖3項演算子は機能しますが、それでも読みにくいと思います。

>>> i=100
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
0
>>> i=101
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
2
>>> i=99
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
1

2番目の式が0を返さなかったのはなぜですか?iが100を超えている
AstralWolf 2016年

6
@AstralWolf:ありがとうございました!これは、私が作成しようとしていた点を完全に示しています。連鎖3項式は可能ですが、読みにくく、明らかに誤解しやすくなります。
Tim Pietzcker

1
もっと読みやすくする必要がある場合は、次のように角かっこを付けることができますa = 1 if i < 100 else (2 if i > 100 else 0)(テストされていませんが、うまくいくと思います)
Zac

@TimPietzcker式とステートメントの違いをどのように説明しますか?
AsheKetchum

62

ケースごとに異なる式のみが必要な場合は、これでうまくいく場合があります。

expr1 if condition1 else expr2 if condition2 else expr

例えば:

a = "neg" if b<0 else "pos" if b>0 else "zero"

1
"pos"ステートメントではなく、式です。
Tim Pietzcker

@TimPietzckerありがとう、より正確になるように投稿を更新しました。
Lycha

20

elseステートメントに別のif句をネストするだけです。しかし、それによって見栄えがよくなるわけではありません。

>>> x=5
>>> x if x>0 else ("zero" if x==0 else "invalid value")
5
>>> x = 0
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'zero'
>>> x = -1
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'invalid value'

1
私にとって、これは最初の条項の構造と概念を維持しているため、受け入れられた回答よりもはるかに読みやすくなっています。ただ主観的な問題。
Ezarate11

12

他のいくつかの回答にもかかわらず:はいそれは可能です:

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

次の1つのライナーに変換されます。

statement1 if expression1 else (statement2 if expression2 else statement3)

実際、無限にそれらをネストすることができます。楽しい ;)


所要時間はどうですか?私が思うに、これらのマルチループははるかに時間がかかります。消費の速度を上げるために、ネストされたループに代わるものが存在する可能性があります。
loveR

こんにちは@loveR、これはループではなく、ネストされたif elseステートメントであり、そのため無視できる時間です
gustavz

7

オプションで、実際getにa のメソッドを使用できますdict

x = {i<100: -1, -10<=i<=10: 0, i>100: 1}.get(True, 2)

getキーの1つが次のように評価されることが保証されている場合、メソッドは必要ありませんTrue

x = {i<0: -1, i==0: 0, i>0: 1}[True]

最大で1つのキーがに評価されるのが理想的Trueです。複数のキーがに評価されるTrue場合、結果は予測できないように見える可能性があります。



4
if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

上記のコードを1行で使用する場合は、以下を使用できます。

x = 2 if i > 100 else 1 if i < 100 else 0

その際、xには、i> 100の場合は2、i <100の場合は1、i = 100の場合は0が割り当てられます。


3

また、表現の性質にも依存します。「それをしない」という他の答えに対する一般的なアドバイスは、総称ステートメントおよび総称式に対して非常に有効です。

ただし、必要なのが「ディスパッチ」テーブルだけである場合、たとえば、指定されたオプションの値に応じて異なる関数を呼び出す場合は、呼び出す関数を辞書内に置くことができます。

何かのようなもの:

def save(): 
   ...
def edit():
   ...
options = {"save": save, "edit": edit, "remove": lambda : "Not Implemented"}

option = get_input()
result = options[option]()

if-elseの代わりに:

if option=="save":
    save()
...

2

人々はすでに三項式について言及しています。例として単純な条件付き代入を使用すると、数式を使用して条件付き代入を実行できる場合があります。これによりコードが読みやすくなることはありませんが、かなり短い1行でコードが読み取られます。あなたの例は次のように書くことができます:

x = 2*(i>100) | 1*(i<100)

比較はTrueまたはFalseになり、数値を掛けると1または0になります。|の代わりに+を使用できます。途中で。


1

三項演算子は、簡潔な表現するための最良の方法です。構文はvariable = value_1 if condition else value_2です。したがって、例として、三項演算子を2回適用する必要があります。

i = 23 # set any value for i
x = 2 if i > 100 else 1 if i < 100 else 0

0

ネストされた三項ifステートメントを使用できます。

# if-else ternary construct
country_code = 'USA'
is_USA = True if country_code == 'USA' else False
print('is_USA:', is_USA)

# if-elif-else ternary construct
# Create function to avoid repeating code.
def get_age_category_name(age):
    age_category_name = 'Young' if age <= 40 else ('Middle Aged' if age > 40 and age <= 65 else 'Senior')
    return age_category_name

print(get_age_category_name(25))
print(get_age_category_name(50))
print(get_age_category_name(75))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.