2013-03-14 88 views
0

我關於Python 2.7.3嘗試很多不同的東西,我碰到這個代碼就來了:爲什麼「或」以這種方式行事?

輸入:

x = 4 
y = 7 
x or y 

輸出:

4 

按照documentor是布爾運算。 是不是or只能產生TrueFalse

所以,我想多一些與此代碼:

輸入:

a = 3 
b = 2 
a or b 

輸出:

3 
在這一點上

然後,我假設的代碼將返回表達的第一個論點。

爲什麼Python給了我這個輸出? Python or操作後面發生了什麼?

+2

鏈接到的文檔解釋了它是如何工作的。 – BrenBarn 2013-03-14 18:36:40

+3

'或'會返回第一個表達式,如果第一個表達式是真的,第二個表達式是假的。 – 2013-03-14 18:36:50

+2

如果你想返回布爾值,你可以使用'bool(x或y)' – Akavall 2013-03-14 18:45:13

回答

3

georgesi的回答完全回答了您提出的具體問題 - 但您鏈接的文檔也是如此,因爲他只是從這些文檔引用。所以,想必你想要更多。

你可能會問兩兩件事:

  1. 爲什麼是Python的設計成這樣,當我的家鄉直覺/最喜歡的語言說:or應該返回bool
  2. 如何這樣做Python工具?

既然你粗體的問題「真的會發生後面的Python or操作什麼」,我猜是後者。

請記住,Python有多種實現方式,只要符合參考文檔設置的規範,他們可以自由實現所需的任何內容。但通常,當人們問「Python如何做到這一點?」時他們的意思是「CPython實現如何做到這一點?」

首先,讓我們來看看一些字節碼:

>>> def f(): 
...  return 1 or 2 
>>> import dis 
>>> dis.dis(f) 
2   0 LOAD_CONST    1 (1) 
      3 JUMP_IF_TRUE_OR_POP  9 
      6 LOAD_CONST    2 (2) 
     >> 9 RETURN_VALUE   

這是什麼意思?在Python式的僞代碼是這樣的:

top = 1 
if top: 
    goto 9 
else: 
    del top 
top = 2 
label 9 
return top 

如果你想更好地瞭解(和CPython的是你所關心的實現),你只需要知道,CPython的字節碼解釋器是一個簡單的堆棧機,並且該堆棧機器的代碼位於文件ceval.c內。所以,我們可以找到JUMP_IF_TRUE_OR_POP代碼here。 (LOAD_CONST操作碼只是將恆定值推入堆棧,以便w = TOP()可以找到它們。我不認爲我們真的需要深入瞭解or的工作原理。)

您可以看到它有點複雜。

主要這是因爲它通過調用bool(top)的C-API相當於之前檢查if top == Falseif top == True優化if top一部分,因爲它處理從bool通話例外。但它也在優化堆棧使用。在沒有解釋DISPATCHFAST_DISPATCH是如何工作的情況下,很難做到太精確,但基本的想法是,它避免了彈出堆棧中的值,以便將它們推回來。

但這就是「Python or操作背後真正發生了什麼?」


您還加粗「是不是or假設產生TrueFalse只?」所以,這使我們回到問題1

首先,請記住,鴨打字是非常核心蟒蛇。 or是應該產生的東西,可以使用,就好像它是重要的任何地方的TrueFalse。你特別應該寫if foo:而不是if foo == True:(或if foo is True:if foo != False:或其他),所以你不應該關心它們之間的區別。

其次,大約有一半的語言與您認爲「布爾操作」應嚴格返回布爾類型值,而其中一半不同意。即使在那些不是以鴨子打字爲基礎的語言中,比如C語言,那麼語言設計師怎麼決定呢?

使得or運算符總是返回bool的「C++風格」避免了副本,允許編譯器更好地執行靜態類型,併爲程序員提供更好的動態類型信息。前兩個在Python中完全不相關,最後一個通常只在編寫依賴於類型的代碼時纔有用,而不是duck typing,通常認爲它是unpythonic。

使其返回第一個真值(或最後一個falsy值)的「C風格」使得實現起來稍微簡單一些,併爲程序員提供了三元式表達式的簡寫。

當Python沒有三元組if - else時,這個調用更容易。現在,也許這是一個更接近的電話 - 尤其是因爲有些人討厭a or b作爲a if a else b的簡寫,並認爲它不合理。

但是歷史已經在那裏了;除非有令人信服的理由,否則任何事情都不會改變,而根據您的口味可能會有相反方向的緊密呼叫並不是一個令人信服的理由。

+0

謝謝。這正是我一直在尋找的。 – 2013-03-14 20:04:05

4

從文檔:

x或y:如果x是假的,那麼y,否則x(1)

爲不同於零的每一個整數,x or y將返回x

0

Python中的or運算符將返回第一個值,如果它被認爲是真的,則返回第一個值,如果第一個值爲假,第二個爲真,則返回第二個值。在這兩種情況都是錯誤的情況下,它將返回False。在這種情況下,4和3都是真值,因此它們被返回。如果替代地使用0,你會看到所述第二值使用

x = 0 
y = 3 
x or y 

這將從返回3

2

doc link你提供:

表達式x或y首先評估X;如果x爲true,則返回值爲 ;否則,評估y並返回結果值 。

1

請注意,or應返回錯誤的對象的唯一情況是兩個操作數都爲false。我們可以看到,在第一個操作數爲真的情況下,我們已經知道兩個操作數都不是假的。這意味着無論第二個操作數是什麼,整個表達式都應該評估爲true。第一個操作數(它是true)被返回。

在第一個操作數(我們稱之爲x)是的情況下,x or y邏輯上等同於y。如果y爲真,則x和y都不是假,因此x or y爲真。如果y爲假,則x和y都是假,因此x or y爲假。這就是爲什麼如果x是假的,返回y。

這種方法稱爲短路評估,當x爲假時,其計算成本較低,因爲y不需要進行不必要的評估。

-1

這有點像一個簡短的陳述。我一直在JS編碼中使用它。

您可以用同樣的方法使用AND

var x = 0; 

x && console.log('x is not truth-y'); 
x || console.log('x is false-y'); 

正如很多其他的人都已經表示,&&||運營商評估表達對他們的左邊,然後,依靠,如果我們談論&&||並根據若評估是真實的或錯誤的,他們會停止,或繼續評估表達式在他們的右側。

+0

這種東西通常不被認爲是Pythonic。首先,在Python中,與JS不同,許多事情不是表達式(比如Python 2.x相當於'console.log','print'語句),所以你不能這樣做。但即使可以,這也不比'if x:print('x is truthy')'更短,並且不太明顯(TOOWTDI是Python禪宗的核心)。 – abarnert 2013-03-16 06:53:48

+0

更重要的是......這與OP的問題實際上沒有關係,甚至在JS中也是如此。在第二個語句中JS是否返回「true」或者是「console.log」的結果並不重要;你只是評估它的副作用。但是OP詢問的是爲什麼Python不返回「true」而不是表達式的值。 – abarnert 2013-03-16 06:56:09

0

這個問題已經得到解答,但你仍然可能會問自己爲什麼這種行爲會有意義。

這裏有一個簡單的用例:

port = int(raw_input("Port number (default 5000): ") or 5000) 

在這種背景下,or(和and)的行爲很完美的感覺。另一個:

url_scheme = enable_https and 'https' or 'http' # although this can be also expressed as: 
url_scheme = 'https' if enable_https else 'http' 
# but i personally prefer the above, because i can read it 
# more easily due to the two possible values being closer together 
相關問題