CS61A: Priority of Boolean Operators: and, or and not
Labの問題よりBoolean関数について優先順位があったこと自体知らなかったので備忘録の意味でメモ。
and
, or
and not
pythonではこの3つのBoolean Operator
をサポートしている。
and
evaluates to True only if both operands evaluate to True. If at least one operand is False, then and evaluates to False.or
evaluates to True if at least one operand evaluates to True. If all operands are False, then or evaluates to False.
と書いてあるがTrue/Falseの値については「プログラマの数学」2章メモ#2 論理積、論理和、ド・モルガンの法則、ベン図、カルノー図、3値論理などでより詳細に書いたのでそちらを参考にしたほうが分かりやすいかもしれない。
Priority
結論から言うと優先順位はnot > and > or
という順番らしい。よってたとえばTrue and not False or not True and False
をevaluationすると(True and (not False)) or ((not True) and False)
となるはずだ。ちなみにこれはTrue
判定になるはず。詳しくはここを参考に。
Truthiness
Pythonの大きな特徴として「全てのオブジェクトをTrue
もしくはFalse
valueとして解釈することが出来る」というものがある。例えばwhile
やif
はTrue
判定が出て初めて処理を始める。ということであらゆる種類のデータを扱うときに「どのようにしてTruthiness(=the quality of being felt to be true, even if not necessarily true)がpython内で定義されているのか」を知るのは非常に大切。
以下の関数を使えば簡単に調べることが可能。
def truthChecker(some_value):
if some_value:
print("YAY")
else:
print("NAY")
def noneChecker(some_value):
if some_value is not None:
print("YAY")
else:
print("NAY")
>>> checks_for_truth("apples"), checks_for_none("apples")
YAY!
YAY!
>>> checks_for_truth([]), checks_for_none([])
BOO!
YAY!
>>> checks_for_truth(""), checks_for_none("")
BOO!
YAY!
>>> checks_for_truth(15), checks_for_none(15)
YAY!
YAY!
>>> checks_for_truth(0), checks_for_none(0) # okay, seeing a pattern
BOO!
YAY!
>>> checks_for_truth(-10), checks_for_none(-10)
YAY!
YAY!
>>> checks_for_truth(None), checks_for_none(None)
BOO!
BOO!
要点だけまとめると
literals | Falthy? | None? |
---|---|---|
[] |
yep | nope |
"" |
yep | nope |
0 |
yep | nope |
None |
yep | yep |
Falsey valueだからといって必ずしもFalseを返すわけではないということ。
>>> [] and 1/0
[]
最初の[]
がFalse
の時点で[]
が全体の値となる。1/0
をevaluateする前に[]
を返してしまっているのでエラーを吐かない。詳しくは一番下を参考に。
Short-cuitという名の"Laziness"
>>> 'a' == ('a' or 'b')
True
>>> 'b' == ('a' or 'b')
False
>>> 'a' == ('a' and 'b')
False
>>> 'b' == ('a' and 'b')
True
>>> 'a' == ('a' or 'b')
True
>>> 'b' == ('a' or 'b')
False
>>> 'a' == ('a' and 'b')
False
>>> 'b' == ('a' and 'b')
True
個人的に一見直感に反する答えが出てきたと思ったがよーく考えると納得がいく。
全体の流れ
ざっくり言うとこんな感じ。
要点は以下のとおり:
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
(Note that neither and nor or restrict the value and type they return to False and True, but rather return the last evaluated argument. This is sometimes useful, e.g., if s is a string that should be replaced by a default value if it is empty, the expression s or 'foo' yields the desired value. Because not has to create a new value, it returns a boolean value regardless of the type of its argument (for example, not 'foo' produces False rather than ''.)
- 括弧内の値を
bool()
してTrue/False判定を行う。以下の表に従ってまず括弧内の値がそもそもTrue/Falseかを確かめる。 -
and
とor
でそれぞれ処理を行う。 - 返ってきた値を左側の値と比較して(上の例題に従えば
==
なので)True/Falseで値を出す。
True | False |
---|---|
1 | 0 |
#s other than 0 | The string 'None' |
Nonempty strings | Empty strings |
Nonempty lists | Empty lists |
Nonempty dictionaries | Empty dictionaries |
or
expressionの動き
- 最初の(括弧内の)ひとつ目の値をとりTrue/False判定を行う。
True
の場合は2へ。False
の場合は3へ。 - (1つめがTrueの場合)は残りの値をチェックせずに1つ目の値をそのまま返す。理由は
or
expressionの特徴より(片方の値がTrue
ならば全体もTrue
になるからである)。(例:'a' == (True or False)
は最初の値True
でTrue
判定を出すのでTrue
が括弧内全体の値として返される。よって'a' == True
がFalse
となりFalse
を返す) - (1つめがFalseの場合)は2番目と進みどこかで
True
を見つけた瞬間2に戻る。全てFalse
の場合はShort-circuitingにより括弧全体の値がexpressionの中の(true or false関係なく)右の値となる。詳しくは一番下の追記を参考に。
>>> False is ('a' == ('' or None or 0)) # ('' or None or 0)全体の値がFalseなので'a' == False (which returns False)は究極False is Falseと同じなのでTrueになる
True
>>> False is ('a' == ('' or None or 'a')) # ('' or None or 'a')全体の値が'a'なのでFalse is ('a' == 'a')つまりFalse is Trueとなり結果Falseとなる。
False
if the first value is evaluated as false Python checks the second half and returns that value. That second half determines the truth value of the whole expression since the first half was false.
この振る舞いをshort circuit
といってpythonがブーリアン値に対して行う反応らしい。
This "laziness" on the part of the interpreter is called "short circuiting" and is a common way of evaluating boolean expressions in many programming languages.
>>> 'a' == (False or 'a')
True
and
expressionの動き
and
expressionも似たような動きをする。
1. 括弧内の一つ目の値がTrue
判定でも(or
のようにすぐTrue
判定を出さずに)残りの値全てをチェックする。これはand
expression特有の動き(and
は両方共True
にならないとTrue
値を返さないため)。どこかでfalse
値を返した瞬間、残りを調べずに全体をFalse
として返す。
2. 括弧内の値がすべてTrue
判定になった場合は最後の値を全体の値として返す。
>>> False is ('a' == ('a' and 1 and 9 and 'b'))
True
>>> False is ('a' == ('a' and 1 and 9 and 'a'))
False
'a' == ('a' and 1 and 2 and 'c' and 'd' and None and 'a') #NoneはFalse valueなので`a`を調べずに括弧内全体の値をFalseとして返す。
False
'a' == ('a' and 1 and 2 and 'c' and 'd' and 'a') #全部True valueなので最後の'a'が括弧内全体の値として返される。
True
or
とand
まとめ
-
or
は括弧内のいづれかがTrue
だった場合はそのTrue
判定を出した値が括弧全体の値として出される。括弧内の値全てがFalse
判定を下した場合は自動的にFalse
となる(=Short-Circuiting) -
and
は1番目がTrue
ならば2番目に行く...(最後まで確認しに行く)。全てTrue
ならば括弧内の最後の値(一番右)を返す。括弧内の内いづれかがFalse
の時点で全体の値が(True/False関係なく)一番左の値が全体のexpressionの値となる。(=Short-circuting)。
'a' == ('' or None or '' or 0 or [] or '' or 'a')
True
'a' == ('' or None or '' or 0 or [] or '' or 'b' or {}) # 左から順番に見ていき'b'がTrue値だと分かったので{}を判定せずに'b'を全体の値として出す。
False
'a' == ('a' and 'a' and 'a')
True
'a' == ('a' and 'a' and '')
False
'a' == ('a' and 'a' and False)
False
'a' == ('a' and 'b' and True and True) #since 'a' == True returns False
False
'a' == ('a' and 1 and 'a' and 9 and 9)
False
'a' == ('a' and 1 and 'a' and 9 and 'a')
True
and
の場合は括弧の中にFalse
値が入ってる時点で速攻でFalse
判定を返す。or
は最初の一個がTrue
ならが他関係なくその最初の値が全体の値として持っていかれる
ではこれは何を返すだろうか?
>>> 'a' == ('a' or None and 0)
上で紹介したPriorityによりNone and 0
を先にTrue/False判定する。結果Falseの値が返ってきて'a' == ('a' or False)
となりTrue
が返ってくる。
>>> 'a' == ('a' or None and 0)
True
この理論に従えば
>>> 'a' == ('b' or None or 0)
False
となるはず。
ちなみに
>>> 'a' == ('b' and 'a' or 0)
True
ということは
>>> 'a' == ('a' and 'b' or 0)
False
になるのも容易にわかるはず。
追記
学校のラボの宿題を解いていて疑問に思ったことと、先生からのレスポンスをまとめておく。
>> False or 0
0
how come 0 evaluates to True when bool(0) evaluates to False?
「0の値はbool(0) # False
なので上の問題は一般化すればFalse or False
。よって返ってくる値は0
ではなくてFalse
になるだろう」というのが俺の予想だったのですが、どうやら間違っていたようです。
Take this longer expression for example:
False or False or False or 0
Once it gets to the last value - the value of the entire expression is dependent on it. If the last value is "truthy" (meaning bool(value) is True) - then the entire expression is "truthy". If the last value is falsey - then the entire expression is falsey. So with that in mind, python can just use the last value directly.Here's another way to think about it:
Is False Truthy? Nope.
Is the second False Truthy? Nope.
Is the third False Truthy? Nope. I've gotten to the last value - well there's no point figuring out if this is truthy or not. At this point the entire expression is dependent on this last value. Might as well just return that as the value.
どうやらor
の時は最後以外全ての値がFalse
となると最後の値のTruthiness/Falseinessに関係なく最後の値を出すようになっているらしいです。
例えば
>>> print(False or False or False or None)
None
False
判定されてそれがこのexpression
の値になると思っていたのですがどうやら最後の値を返り値として出すようです。
>>> s = ""
>>> s or "foo"
'foo'
>>> s and "foo"
''
参考にしたリンク
Author And Source
この問題について(CS61A: Priority of Boolean Operators: and, or and not), 我々は、より多くの情報をここで見つけました https://qiita.com/weedslayer/items/2d1778d38ebcf7d02d1b著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .