python goIf について
Qiitaのpythongolfについての記事を読んでいて、どうしても理解できないことがあったので質問させていただきます。下のコードでは、a<bが「偽」のとき何故bが代入されるのでしょうか?私の理解している仕組みだと、Falseが代入されてしまう気がします。
該当のソースコード
python
1c = a<b and a or b
調べてみて理解できたこと
ブール値以外でもand、orは使える。if文の中でなくてもand、orは使える。
・or の左が「真」の場合、左の値を返す ・or の左が「偽」の場合、右の値を返す
・and の左が「真」の場合、右の値を返す ・and の左が「偽」の場合、左の値を返す
###どのように動作すると考えているか
- a,bを比較(False場合)
- and の左が「偽」の場合、左の値を返すので、Falseが代入される
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
ベストアンサー
- and の左が「偽」の場合、左の値を返すので、Falseが代入される
ちょっと違います。
c = a<b and a or b
の場合、
c = (((a<b) and a) or b)
という評価順序なので、
(a<b) が True ならば ((a<b) and a) の部分が a になる。つまり c = a or b になる。
さらに、bool(a) が True ならば c = a 、False ならば c = b になる。
(a<b) が False ならば ((a<b) and a) の部分が False になる。つまり c = False or b になる。
さらに、False or b は b になり、c = b になる。
bool(a) が False 判定される場合に注意が必要。
>>> True and 1 or 2 1 >>> True and 0 or 2 2 >>> False and 1 or 2 2 >>> False and 0 or 2 2
投稿2019/11/29 11:19
編集2019/11/29 11:23総合スコア5406
0
左結合(left-associativeであって)なのでこう評価される。
python
1>>> (False and "A") or "B" 2'B'
カッコ内の評価が終わっても、後ろがor
なので全体の真理値を決定するには"B"
まで見る必要がある。
投稿2019/11/29 11:09
編集2019/11/29 11:13総合スコア30935
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
python
1c = a<b and a or b
は、演算子の優先順位を()で明示すると
python
1c = ((a<b) and a ) or b
となります。これを2個の式に分けますと、
python
1d = (a<b) and a 2c = d or b
となります。
a,bを比較(False場合)
and の左が「偽」の場合、左の値を返すので、Falseが代入される
は d=... の動作となります。その後に、c=...で
or の左が「真」の場合、左の値を返す ・or の左が「偽」の場合、右の値を返す
が適用されて (Falseの場合)は d が「偽」となり、「右の値」すなわちbが返ります。
投稿2019/11/29 11:10
総合スコア902
0
短絡評価あたりの仕様の話ですかね。
常識的に考えると「A and B」は
Aがtrue かつ Bがtrue ならば true さもなくば false
言い換えると
Aがtrueならば Bがtrueならばtrue ※ Bがfalseならばfalse ※ Aがfalseならば (Bがtrueでもfalseでも) false
です。
しかし、※の部分が無駄に感じますね。これならば
Aがtrueならば B Aがfalseならば false
としてしまっても「Bがブール値のときは」同じ結果になります。
というわけで、言語によってはこのような時Bを返す仕様になっていることがあります。
orも同様。
Bがブール値でないときも、普通に使っていればブール値に変換されてから評価されますので問題ありません。
普通に使わないと、今回のようによく分からないことになります。
コードゴルフは、しばしば物を普通に使わないものです。
指摘のあったように上記の説明はpythonの仕様とは異なっていたようですが、
なんにせよ、論理演算子は言語によっては「ブールが入ったときは普通の論理演算になるが、それ以外が入ると論理演算とは違う何かになる」という点が今回のポイントです。
投稿2019/11/30 06:43
編集2019/12/04 01:06総合スコア3047
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/12/02 20:00
2019/12/02 20:03
2019/12/04 01:07
0
この回答は他の方の、特にshiracamusさんの回答の補足です。
元の記事は
python
1def f(a, b): 2 if a < b: 3 return a 4 else: 5 return b
じゃなくて
python
1f=lambda a,b: a<b and a or b
と書く方が短くて済むという話だと思うのですけれど、これら2つのコードは同じ意味でもなければ、同じ動きをするコードでもありません。(理由と説明は他の方の回答の通りなので省きます)
その記事は悪く言うと嘘もしくは間違い、悪く言わなくても「使い道が限定されていることを端折っている正確ではない記事」です。
つまり、その記事を読んで
a<bが「偽」のときbが代入される
と認識したのが誤りです。
おそらくですが、a>0かつb>0であることが前提として示されている場合などにはこういうテクニックもあるよ、というような話だったんだろうと思います。
(説明の時にうっかり省いてしまったのか、書いた人が理解できていないのかは判断できませんので、よい方で解釈すると、ということで)
追記
全く本筋じゃないですが
python
1f=lambda a,b:[b,a][a<b]
の方が短いだろ、と思いました。
ここは取り消します
追記
考えみたらf=min
で済む内容なので(注:min
が3回呼ばれる場合にはf
に束縛した方が全体を短くできる)そもそも話がおかしいわけで、ということはおおもとの趣旨は
python
1def f(a, b): 2 if a < b: 3 return c() 4 else: 5 return d()
より
python
1f=lambda a,b: a<b and c() or d()
の方が短い、ただしc()
が真値を返すという保証がある場合だけ、みたいな話だったのではないでしょうか?
それならmin
では済まないし、f=lambda a,b:[c(),d()][a<b]
でも解決しない(c()
とd()
の2つの式が両方評価されてしまう)ので多少の意味はあるかな、と思いました。
そういう前提とかいったものが伝言ゲームの過程で無くなっていって、まったくの無意味な話になったのではないかな、と想像します。
投稿2019/11/29 12:52
編集2019/11/29 14:15総合スコア11231
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/11/29 13:32
2019/11/29 13:50 編集
退会済みユーザー
2019/11/30 07:21
2019/12/02 20:14 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/12/02 20:01