「if」ステートメントで複数行の条件をスタイリングしますか?
-
05-07-2019 - |
質問
if
sの長い条件をいくつかの行に分割することがあります。これを行う最も明白な方法は次のとおりです。
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
アクションは条件と調和するため、視覚的にはあまり魅力的ではありません。ただし、4つのスペースの正しいPythonインデントを使用する自然な方法です。
今のところ、私が使用しているもの:
if ( cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
しかし、これはあまりきれいではありません。 :-)
別の方法を推奨できますか?
解決
2番目の条件行で4つのスペースを使用する必要はありません。たぶん使用:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
また、空白はあなたが考えるよりも柔軟であることを忘れないでください:
if (
cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'
):
do_something
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
これらはどちらもかなりいです。
括弧を失う可能性があります(スタイルガイドがっかりします)?
if cond1 == 'val1' and cond2 == 'val2' and \
cond3 == 'val3' and cond4 == 'val4':
do_something
これにより、少なくともいくつかの差別化が得られます。
または偶数:
if cond1 == 'val1' and cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
私が好むと思う:
if cond1 == 'val1' and \
cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
スタイルガイドは、 2010年以降)ブラケットの使用を推奨しています。
他のヒント
単純なANDまたはORの縮退したケースでは、次のことに頼りました。
if all( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
if any( [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4'] ):
数文字を削り、条件に微妙がないことを明確にします。
誰かは、ここで垂直方向の空白の使用を支持しなければなりません! :)
if ( cond1 == val1
and cond2 == val2
and cond3 == val3
):
do_stuff()
これにより、各条件が明確に表示されます。また、より複雑な条件をより明確に表現できます。
if ( cond1 == val1
or
( cond2_1 == val2_1
and cond2_2 >= val2_2
and cond2_3 != bad2_3
)
):
do_more_stuff()
はい、わかりやすくするために、垂直の不動産を少しトレードオフしています。 IMOの価値は十分にあります。
これは私の個人的な見解です:長い条件は(私の見解では)ブール値を返す関数/メソッドへのリファクタリングを示唆するコードの匂いです。例:
def is_action__required(...):
return (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4')
今、複数行の条件を適切に表示する方法を見つけた場合、おそらくそれらを持っていることに満足し、リファクタリングをスキップします。
一方、それらを私の美意識を乱すことは、リファクタリングの動機として機能します。
したがって、私の結論は、複数の回線状態がいように見えるはずであり、これがそれらを回避するインセンティブであるということです。
これはそれほど改善しませんが...
allCondsAreOK = (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4')
if allCondsAreOK:
do_something
if-conditionが非常に大きい場合、このスタイルを好みます:
if (
expr1
and (expr2 or expr3)
and hasattr(thingy1, '__eq__')
or status=="HappyTimes"
):
do_stuff()
else:
do_other_stuff()
and
キーワードを2行目に移動し、条件を含むすべての行を4つではなく2つのスペースでインデントすることをお勧めします。
if (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4'):
do_something
これは、まさにコードでこの問題を解決する方法です。行の最初の単語としてキーワードを使用すると、条件がはるかに読みやすくなり、スペースの数を減らすと、条件とアクションがさらに区別されます。
PEP 0008 (Pythonの公式スタイルガイド)を引用する価値があるようです。適度な長さでこの問題についてコメントしているため:
if
if
の条件部分が複数行にまたがって記述できるほど長い場合、2文字のキーワードの組み合わせ(つまり、if
)、1つのスペース、および開始かっこは、複数行の条件の後続の行に自然な4スペースのインデントを作成します。これにより、if
-statement内にネストされたインデントされたコードスイートと視覚的に競合する可能性があり、これも当然4つのスペースにインデントされます。このPEPは、そのような条件付き行をif
ステートメント内のネストされたスイートからさらに視覚的に区別する方法(またはどうか)について明示的な位置をとりません。この状況で受け入れられるオプションには次のものがありますが、これらに限定されません:# No extra indentation. if (this_is_one_thing and that_is_another_thing): do_something() # Add a comment, which will provide some distinction in editors # supporting syntax highlighting. if (this_is_one_thing and that_is_another_thing): # Since both conditions are true, we can frobnicate. do_something() # Add some extra indentation on the conditional continuation line. if (this_is_one_thing and that_is_another_thing): do_something()
「限定されない」ことに注意してください;上記の引用で;スタイルガイドで提案されているアプローチに加えて、この質問に対する他の回答で提案されているもののいくつかも受け入れられます。
ここに私がしていることを思い出してください。および「すべて」反復可能を受け入れるので、リストに長い条件を入れて「すべて」を許可します。仕事をします。
condition = [cond1 == 'val1', cond2 == 'val2', cond3 == 'val3', cond4 == 'val4']
if all(condition):
do_something
希望するソリューションが表示されないことに驚いています
if (cond1 == 'val1' and cond2 == 'val2'
and cond3 == 'val3' and cond4 == 'val4'):
do_something
and
はキーワードであるため、エディターによって強調表示され、その下のdo_somethingとはかなり異なって見えます。
個人的には、長いif文に意味を追加したいです。適切な例を見つけるためにコードを検索する必要がありますが、頭に浮かぶ最初の例は次のとおりです:たとえば、多くの変数に応じて特定のページを表示したいという奇妙なロジックに遭遇したとします。
英語:"ログインしているユーザーが管理者の教師ではなく、通常の教師であり、学生自身ではない場合..."
if not user.isAdmin() and user.isTeacher() and not user.isStudent():
doSomething()
確かにこれは問題ないように見えますが、ifステートメントを読むのは大変な作業です。理にかなっているラベルにロジックを割り当てるのはどうですか。 「ラベル」実際には変数名です:
displayTeacherPanel = not user.isAdmin() and user.isTeacher() and not user.isStudent()
if displayTeacherPanel:
showTeacherPanel()
これは馬鹿げているように思えるかもしれませんが、教師パネルを表示している場合、またはユーザーがデフォルトで他の特定のパネルにアクセスできる場合にのみ、別のアイテムを表示したいという別の条件があります:
if displayTeacherPanel or user.canSeeSpecialPanel():
showSpecialPanel()
変数を使用せずにロジックを保存およびラベル付けせずに上記の条件を記述してみてください。非常に面倒で読みにくい論理ステートメントになるだけでなく、繰り返してしまいます。合理的な例外はありますが、覚えておいてください:自分自身を繰り返さない(DRY)。
" all"および「すべて」同じタイプのケースの多くの条件に適しています。しかし、彼らは常にすべての条件を評価します。この例に示すように:
def c1():
print " Executed c1"
return False
def c2():
print " Executed c2"
return False
print "simple and (aborts early!)"
if c1() and c2():
pass
print
print "all (executes all :( )"
if all((c1(),c2())):
pass
print
(固定幅の名前は実際のコードの代表ではないため、識別子を少し変更しました–少なくとも私が遭遇する実際のコードではありません–そして、例の読みやすさを信じています。)
if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4"):
do_something
これは" and"に適しています。および「または」 (最初の行が2行目であることが重要です)が、他の長い条件ではそうではありません。幸い、前者はより一般的なケースのようですが、後者は一時変数で簡単に書き換えられることがよくあります。 (通常は難しいことではありませんが、書き換え時に「and」および「/」または「or」の短絡を維持することは困難であるか、それほど明白ではない/読みにくい場合があります。
C ++に関するブログ投稿、C ++スタイルが同じであることを含めます:
if (cond1 == "val1" and cond22 == "val2"
and cond333 == "val3" and cond4444 == "val4") {
do_something
}
@krawyotiの発言に加えて...長い条件は、読みにくく理解しにくいために臭いがします。関数または変数を使用すると、コードが明確になります。 Pythonでは、式が「浮動」のように見えないように、垂直スペースを使用し、括弧を囲み、各行の先頭に論理演算子を配置することを好みます。
conditions_met = (
cond1 == 'val1'
and cond2 == 'val2'
and cond3 == 'val3'
and cond4 == 'val4'
)
if conditions_met:
do_something
while
ループのように、条件を複数回評価する必要がある場合は、ローカル関数を使用するのが最適です。
シンプルでシンプル、pep8チェックもパスします:
if (
cond1 and
cond2
):
print("Hello World!")
最近、 all
と any
の機能を好んでいます。AndとOrの比較を組み合わせることはめったにないので、これはうまく機能し、Failing Earlyの追加の利点もあります。ジェネレーター内包表記:
if all([
cond1,
cond2,
]):
print("Hello World!")
イテレート可能オブジェクトを1つ渡すことを忘れないでください! N引数を渡すことは正しくありません。
注: any
は多くの or
比較のようなもので、 all
は多くの and
比較のようなものです。
これは、ジェネレータの内包表記とうまく組み合わされます。例:
# Check if every string in a list contains a substring:
my_list = [
'a substring is like a string',
'another substring'
]
if all('substring' in item for item in my_list):
print("Hello World!")
# or
if all(
'substring' in item
for item in my_list
):
print("Hello World!")
詳細:ジェネレーターの理解
条件と本文の間に追加の空白行を挿入し、残りを正規の方法で行う場合はどうなりますか?
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
p.s。私は常にスペースではなくタブを使用しています。微調整できません...
完全を期すために、いくつかの他のランダムなアイデア。彼らがあなたのために働くなら、それらを使用してください。それ以外の場合は、おそらく他のことを試してみることをお勧めします。
辞書を使用してこれを行うこともできます:
>>> x = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> y = {'cond1' : 'val1', 'cond2' : 'val2'}
>>> x == y
True
このオプションはより複雑ですが、便利な場合もあります。
class Klass(object):
def __init__(self, some_vars):
#initialize conditions here
def __nonzero__(self):
return (self.cond1 == 'val1' and self.cond2 == 'val2' and
self.cond3 == 'val3' and self.cond4 == 'val4')
foo = Klass()
if foo:
print "foo is true!"
else:
print "foo is false!"
Dunnoはそれがあなたのために働くなら、それは考慮するべきもう一つのオプションです。もう1つの方法を次に示します。
class Klass(object):
def __init__(self):
#initialize conditions here
def __eq__(self):
return (self.cond1 == 'val1' and self.cond2 == 'val2' and
self.cond3 == 'val3' and self.cond4 == 'val4')
x = Klass(some_values)
y = Klass(some_other_values)
if x == y:
print 'x == y'
else:
print 'x!=y'
最後の2つはテストしていませんが、それがあなたがやりたいことなら、コンセプトはあなたを動かすのに十分なはずです。
(また、記録については、これが1回限りの場合は、おそらく最初に提示した方法を使用した方がよいでしょう。多くの場所で比較を行う場合、これらの方法は読みやすさを向上させる可能性がありますそれらが一種のハックであるという事実についてそれほど悪く感じないようにするのに十分です。)
私が普段していることは:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'
):
do_something
こうすることで、閉じ括弧とコロンが条件の終了を視覚的に示します。
これを行うための適切な方法を見つけるのに苦労してきたので、アイデアを思いつきました(これは主に趣味の問題なので、特効薬ではありません)。
if bool(condition1 and
condition2 and
...
conditionN):
foo()
bar()
私が見た他のソリューションと比較して、このソリューションにはいくつかのメリットがあります。つまり、インデント(bool)の余分な4スペースが得られ、すべての条件を垂直に揃えることができ、ifステートメントの本体は明確な(インシュレーション)方法でインデントされます。これはブール演算子の短絡評価の利点も保持しますが、もちろん基本的に何もしない関数呼び出しのオーバーヘッドを追加します。引数を返す任意の関数をブールの代わりにここで使用できると(有効に)主張することができますが、私が言ったように、それは単なるアイデアであり、最終的には好みの問題です。
おもしろい、これを書いて「問題」について考えていたので、関数呼び出しのオーバーヘッドを取り除くさらに別のアイデアを思いつきました。余分な括弧のペアを使用して、複雑な条件を入力しようとしていることを示さないのはなぜですか?さらに2つ言って、ifステートメントの本体に関連するサブ条件の素敵な2スペースのインデントを指定します。例:
if (((foo and
bar and
frob and
ninja_bear))):
do_stuff()
このようなものを見ると、"ちょっと、ここで複雑なことが起こっています!と言うベルがすぐに頭に鳴ります。はい、括弧は読みやすさには役立ちませんが、これらの条件はめったに表示されないはずであり、表示された場合は、とにかく停止して注意深く読む必要があります(複雑なため strong>)。
とにかく、私がここで見たことのない、さらに2つの提案。これが誰かを助けることを願っています:)
2行に分割できます
total = cond1 == 'val' and cond2 == 'val2' and cond3 == 'val3' and cond4 == val4
if total:
do_something()
または一度に1つの条件を追加することもできます。そうすれば、少なくとも if
からクラッタが分離されます。
このスレッドは古いことは知っていますが、Python 2.7コードがいくつかあり、PyCharm(4.5)はこのケースについてまだ文句を言います:
if foo is not None:
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
# some comment about do_something
do_something
PEP8警告「次の論理行と同じインデントで視覚的にインデントされた行」でも、実際のコードは完全に問題ありませんか? 「インデントしすぎない?」ではありません
... Pythonが弾丸を食い尽くして、ちょうど中括弧で終わることを望む場合があります。偶然の誤ったインデントのために、長年にわたって偶然にいくつのバグが導入されたのだろうか...
ifステートメントに複数条件も提供するすべての回答者は、提示された問題と同じくらいいです。同じことを行ってもこの問題を解決することはできません。
PEP 0008の回答でさえ反発的です。
これははるかに読みやすいアプローチです
condition = random.randint(0, 100) # to demonstrate
anti_conditions = [42, 67, 12]
if condition not in anti_conditions:
pass
言葉を食べたいですか?多条件式が必要だと私に納得させてください。文字通りこれを印刷して、あなたの娯楽のために食べます。
@zkandaのソリューションは、ちょっとしたひねりを加えても良いと思います。それぞれのリストに条件と値がある場合は、リストの内包表記を使用して比較を行うことができます。これにより、条件/値のペアを追加するために少し一般的になります。
conditions = [1, 2, 3, 4]
values = [1, 2, 3, 4]
if all([c==v for c, v in zip(conditions, values)]):
# do something
このようなステートメントをハードコーディングしたい場合、読みやすくするために次のように記述します。
if (condition1==value1) and (condition2==value2) and \
(condition3==value3) and (condition4==value4):
さらに、 を使用して別のソリューションをスローします。 iand
演算子:
proceed = True
for c, v in zip(conditions, values):
proceed &= c==v
if proceed:
# do something
条件をリストにまとめてから、やり直してください。のような:
if False not in Conditions:
do_something
条件が長い場合、コード本体が短いことがよくあります。その場合、本文をダブルインデントするだけです。
if (cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4'):
do_something
if cond1 == 'val1' and \
cond2 == 'val2' and \
cond3 == 'val3' and \
cond4 == 'val4':
do_something
またはこれが明確な場合:
if cond1 == 'val1'\
and cond2 == 'val2'\
and cond3 == 'val3'\
and cond4 == 'val4':
do_something
この場合、インデントが4の倍数であるべき理由はありません。 "開始区切り文字に合わせて調整 ''を参照してください:
別のアプローチを次に示します。
cond_list = ['cond1 == "val1"','cond2=="val2"','cond3=="val3"','cond4=="val4"']
if all([eval(i) for i in cond_list]):
do something
これにより、リストに別の条件を追加するだけで、ifステートメントを変更せずに別の条件を簡単に追加することもできます。
cond_list.append('cond5=="val5"')
私は通常使用します:
if ((cond1 == 'val1' and cond2 == 'val2' and
cond3 == 'val3' and cond4 == 'val4')):
do_something()
if& else条件は、以下のように記述できるよりも、その内部で複数のステートメントを実行する必要があります。 その中に1つのステートメントがあるif elseの例があるときはいつでも。
ご協力ありがとうございます。
#!/usr/bin/python
import sys
numberOfArgument =len(sys.argv)
weblogic_username =''
weblogic_password = ''
weblogic_admin_server_host =''
weblogic_admin_server_port =''
if numberOfArgument == 5:
weblogic_username = sys.argv[1]
weblogic_password = sys.argv[2]
weblogic_admin_server_host =sys.argv[3]
weblogic_admin_server_port=sys.argv[4]
elif numberOfArgument <5:
print " weblogic UserName, weblogic Password and weblogic host details are Mandatory like, defalutUser, passwordForDefaultUser, t3s://server.domainname:7001 ."
weblogic_username = raw_input("Enter Weblogic user Name")
weblogic_password = raw_input('Enter Weblogic user Password')
weblogic_admin_server_host = raw_input('Enter Weblogic admin host ')
weblogic_admin_server_port = raw_input('Enter Weblogic admin port')
#enfelif
#endIf