Python มีตัวดำเนินการแบบเงื่อนไขหรือไม่


6043

ถ้า Python ไม่มีตัวดำเนินการเงื่อนไขที่ประกอบไปด้วยสามมันเป็นไปได้ที่จะจำลองโดยใช้โครงสร้างภาษาอื่นหรือไม่?


149
ในเอกสารอย่างเป็นทางการของ Python 3.0 ที่อ้างถึงในความคิดเห็นด้านบนสิ่งนี้เรียกว่า "conditional_expressions" และมีการกำหนดอย่างเข้ารหัสลับ เอกสารดังกล่าวไม่ได้รวมคำว่า "ประกอบไปด้วยสาม" ดังนั้นคุณจะกดยากที่จะหามันผ่านทาง Google จนกว่าคุณจะรู้ว่าสิ่งที่จะมองหา เอกสารรุ่นที่ 2จะค่อนข้างเป็นประโยชน์มากขึ้นและรวมถึงการเชื่อมโยงไปยัง"PEP 308"ซึ่งรวมถึงจำนวนมากของบริบททางประวัติศาสตร์ที่น่าสนใจที่เกี่ยวข้องกับคำถามนี้
สูงศักดิ์

26
"ternary" (มีสามอินพุต) เป็นคุณสมบัติที่ตามมาของการกระตุ้นนี้ไม่ใช่คุณสมบัติที่กำหนดของแนวคิด เช่น: SQL มีcase [...] { when ... then ...} [ else ... ] endผลคล้ายกัน แต่ไม่ได้ประกอบไปด้วยสามส่วน
user313114

10
นอกจากนี้ ISO / IEC 9899 (มาตรฐานภาษาโปรแกรม C) ส่วน 6.5.15 เรียกมันว่า "ตัวดำเนินการแบบมีเงื่อนไข"
user313114

9
Wikipedia ครอบคลุมเนื้อหานี้อย่างละเอียดในบทความ " ?: "
HelloGoodbye

9
ในปีที่ผ่านมาตั้งแต่ความคิดเห็นของผู้ดีงามเอกสารการแสดงออกตามเงื่อนไขได้รับการปรับปรุงเพื่อบอกว่าการแสดงออกแบบมีเงื่อนไข (บางครั้งเรียกว่า "ผู้ประกอบการที่สาม") ...
Scott Martin

คำตอบ:


7042

ใช่มันถูกเพิ่มเข้ามาในเวอร์ชั่น 2.5 ไวยากรณ์นิพจน์คือ:

a if condition else b

ครั้งแรกที่conditionได้รับการประเมินแล้วว่าหนึ่งอย่างใดอย่างหนึ่งaหรือbได้รับการประเมินและกลับมาอยู่บนพื้นฐานของบูลีนconditionมูลค่าของ หากconditionประเมินTrueแล้วaมีการประเมินและกลับ แต่bถูกละเว้นหรืออื่น ๆ เมื่อbมีการประเมินและกลับมา แต่aจะถูกละเว้น

สิ่งนี้ยอมให้มีการลัดวงจรเนื่องจากเมื่อconditionมีการaประเมินความจริงเท่านั้นและbไม่ได้รับการประเมินเลย แต่เมื่อconditionมีการbประเมินค่าเท็จเท่านั้นและaไม่ได้รับการประเมินเลย

ตัวอย่างเช่น:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

โปรดทราบว่าเงื่อนไขเป็นแสดงออกไม่ได้เป็นคำสั่ง ซึ่งหมายความว่าคุณไม่สามารถใช้คำสั่งมอบหมายหรือpassหรือข้อความอื่น ๆภายในนิพจน์เงื่อนไข:

>>> pass if False else x = 3
  File "<stdin>", line 1
    pass if False else x = 3
          ^
SyntaxError: invalid syntax

อย่างไรก็ตามคุณสามารถใช้นิพจน์เงื่อนไขเพื่อกำหนดตัวแปรดังนี้:

x = a if True else b

คิดว่านิพจน์เงื่อนไขเป็นการสลับระหว่างค่าสองค่า มันมีประโยชน์มากเมื่อคุณอยู่ในสถานการณ์ 'หนึ่งค่าหรือสถานการณ์อื่น' แต่จะไม่ทำอะไรมาก

หากคุณจำเป็นต้องใช้งบที่คุณต้องใช้ปกติif คำสั่งแทนเงื่อนไขการแสดงออก


โปรดทราบว่า Pythonist ถูกขมวดคิ้วด้วยเหตุผลหลายประการ:

  • คำสั่งของข้อโต้แย้งนั้นแตกต่างจากcondition ? a : bตัวดำเนินการแบบไตรภาคจากภาษาอื่น ๆ (เช่น C, C ++, Go, Perl, Ruby, Java, Javascript, ฯลฯ ) ซึ่งอาจนำไปสู่ข้อผิดพลาดเมื่อผู้คนไม่คุ้นเคยกับ Python " พฤติกรรมที่น่าแปลกใจใช้มัน (พวกเขาอาจกลับคำสั่งโต้แย้ง)
  • บางคนพบว่ามัน "เทอะทะ" เพราะมันตรงกันข้ามกับการไหลของความคิดปกติ (คิดถึงสภาพก่อนแล้วจึงเกิดผลกระทบ)
  • โวหารเหตุผล (แม้ว่า 'อินไลน์if' จะมีประโยชน์จริง ๆและทำให้สคริปต์ของคุณกระชับยิ่งขึ้น แต่ก็ทำให้โค้ดของคุณซับซ้อนยิ่งขึ้น)

หากคุณมีปัญหาในการจดจำคำสั่งซื้อโปรดจำไว้ว่าเมื่ออ่านออกเสียงคุณ (เกือบ) จะพูดในสิ่งที่คุณหมายถึง ยกตัวอย่างเช่นจะอ่านออกเสียงเป็นx = 4 if b > 8 else 9x will be 4 if b is greater than 8 otherwise 9

เอกสารอย่างเป็นทางการ:


268
คำสั่งนี้อาจดูแปลกสำหรับนักเขียนโค้ด แต่f(x) = |x| = x if x > 0 else -xฟังดูเป็นธรรมชาติสำหรับนักคณิตศาสตร์ คุณอาจเข้าใจเช่นเดียวกับ A ในกรณีส่วนใหญ่ยกเว้นเมื่อ C คุณควรทำ B แทน ...
yota

121
ระวังลำดับการใช้งานเมื่อใช้สิ่งนี้ z = 3 + x if x < y else yยกตัวอย่างเช่นบรรทัด ถ้าx=2และy=1คุณอาจคาดหวังว่าจะให้ผลตอบแทน 4 แต่จริง ๆ แล้วจะให้ผลตอบแทน 1 z = 3 + (x if x > y else y)คือการใช้งานที่ถูกต้อง
Kal Zekdor

11
ประเด็นคือถ้าคุณต้องการประเมินผลเพิ่มเติมหลังจากประเมินเงื่อนไขเช่นเพิ่มมูลค่าให้กับผลลัพธ์คุณจะต้องเพิ่มนิพจน์เพิ่มเติมทั้งสองด้าน ( z = 3 + x if x < y else 3 + y) หรือจัดกลุ่มตามเงื่อนไข ( z = 3 + (x if x < y else y)หรือz = (x if x < y else y) + 3)
Kal Zekdor

4
@MrGeek ฉันเห็นสิ่งที่คุณหมายถึงดังนั้นโดยทั่วไปคุณจะทำรังการดำเนินงาน: `" foo "ถ้า Bool อื่น (" บาร์ "ถ้า Bool อื่น" foobar ")`
Dimesio

3
โปรแกรมเมอร์ต้องการการกำหนดสูตรที่ถูกต้องมากกว่านักคณิตศาสตร์เพราะในวิชาคณิตศาสตร์มักจะมีแนวความคิดพื้นฐานอยู่เสมอ อาร์กิวเมนต์ที่น่าเชื่อถือคือโอเปอเรเตอร์% การเลียนแบบวิธีการใช้ "mod" ในคณิตศาสตร์จะเป็นหายนะ ไม่ฉันไม่ยอมรับข้อโต้แย้งของคุณ มันก็เหมือนกับการปฏิบัติตามหน่วยจักรวรรดิ Groetjes Albert
Albert van der Horst

797

คุณสามารถจัดทำดัชนีเป็นสิ่งอันดับ:

(falseValue, trueValue)[test]

testความต้องการที่จะกลับมาทรูหรือเท็จ
มันอาจปลอดภัยกว่าที่จะใช้มันเป็น:

(falseValue, trueValue)[test == True]

หรือคุณสามารถใช้บิวด์อินbool()เพื่อรับรองค่าบูลีน :

(falseValue, trueValue)[bool(<expression>)]

590
โปรดทราบว่าสิ่งนี้จะประเมินทุกสิ่งเสมอในขณะที่โครงสร้าง if / else จะประเมินเฉพาะนิพจน์ที่ชนะ
SilverbackNet

117
(lambda: print("a"), lambda: print("b"))[test==true]()
ดัสตินเก็ตซ์

15
ควรสังเกตว่าสิ่งที่อยู่ภายใน[]ของสามารถแสดงออกโดยพลการ นอกจากนี้เพื่อความปลอดภัยของคุณอย่างชัดเจนสามารถทดสอบ truthiness [bool(<expression>)]โดยการเขียน bool()ฟังก์ชั่นได้รับรอบตั้งแต่ v2.2.1
martineau

12
ฉันได้ทำเคล็ดลับที่คล้ายกัน - เพียงครั้งเดียวหรือสองครั้ง แต่ทำมัน - โดยการจัดทำดัชนีในพจนานุกรมด้วยTrueและFalseเป็นกุญแจ: {True:trueValue, False:falseValue}[test] ฉันไม่รู้ว่านี่มีประสิทธิภาพน้อยกว่าหรือไม่ แต่อย่างน้อยก็หลีกเลี่ยงทั้งหมด การอภิปราย "สง่างาม" และ "น่าเกลียด" ไม่มีความกำกวมที่คุณต้องจัดการกับบูลีนแทนที่จะเป็นแบบอินไลน์
JDM


338

สำหรับรุ่นก่อน 2.5 มีเคล็ดลับ:

[expression] and [on_true] or [on_false]

มันสามารถให้ผลลัพธ์ที่ผิดเมื่อon_true มีค่าบูลีนเท็จ 1
แม้ว่ามันจะมีประโยชน์ในการประเมินการแสดงออกจากซ้ายไปขวาซึ่งเป็นที่ชัดเจนในความคิดของฉัน

1. มีเทียบเท่าของ C”?:” ผู้ประกอบการที่สาม?


67
วิธีแก้ไขคือใช้ (ทดสอบและ [true_value] หรือ [false_value]) [0] ซึ่งจะหลีกเลี่ยงกับดักนี้
ThomasH

5
ผู้ประกอบการที่สามมักจะดำเนินการได้เร็วขึ้น (บางครั้งโดย 10-25%)
ภูเขาไฟ

7
@volcano คุณมีแหล่งสำหรับฉันหรือไม่
OrangeTux

4
@OrangeTux นี่คือรหัส disassembled การใช้วิธีการที่ ThomasH แนะนำจะยิ่งช้ากว่าเดิม
mbomb007

265

<expression 1> if <condition> else <expression 2>

a = 1
b = 2

1 if a > b else -1 
# Output is -1

1 if a > b else -1 if a < b else 0
# Output is -1

83
สิ่งนี้เน้นความตั้งใจหลักของผู้ประกอบการที่ประกอบไปด้วย: การเลือกค่า นอกจากนี้ยังแสดงให้เห็นว่ามากกว่าหนึ่งประกอบไปด้วยสามสามารถถูกผูกมัดเข้าด้วยกันในการแสดงออกเดียว
Roy Tinker

6
@ Craig ฉันเห็นด้วย แต่ก็มีประโยชน์เช่นกันหากจะรู้ว่าจะเกิดอะไรขึ้นเมื่อไม่มีวงเล็บ ในรหัสจริงฉันก็มักจะใส่ parens ชัดเจน
Jon Coombs

158

จากเอกสาร :

เงื่อนไขบางอย่าง (บางครั้งเรียกว่า

การแสดงออกx if C else yครั้งแรกประเมินสภาพC ( ไม่ใช่ x ); ถ้าCเป็นจริงxจะถูกประเมินและส่งคืนค่าของมัน มิฉะนั้นจะถูกประเมินyและส่งคืนค่าของมัน

ดูPEP 308สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับนิพจน์ที่มีเงื่อนไข

ใหม่ตั้งแต่รุ่น 2.5


120

ผู้ประกอบการสำหรับการแสดงออกเงื่อนไขในหลามถูกเพิ่มเข้ามาในปี 2006 เป็นส่วนหนึ่งของงูหลามการเพิ่มประสิทธิภาพของการเสนอ 308 รูปแบบมันแตกต่างจาก?:ผู้ประกอบการทั่วไปและมัน:

<expression1> if <condition> else <expression2>

ซึ่งเทียบเท่ากับ:

if <condition>: <expression1> else: <expression2>

นี่คือตัวอย่าง:

result = x if a > b else y

ไวยากรณ์อื่นที่สามารถใช้ (เข้ากันได้กับรุ่นก่อน 2.5):

result = (lambda:y, lambda:x)[a > b]()

ที่ถูกดำเนินการได้รับการประเมินอย่างเฉื่อยชา

อีกวิธีคือการจัดทำดัชนี tuple (ซึ่งไม่สอดคล้องกับตัวดำเนินการตามเงื่อนไขของภาษาอื่น ๆ ส่วนใหญ่):

result = (y, x)[a > b]

หรือพจนานุกรมที่สร้างขึ้นอย่างชัดเจน:

result = {True: x, False: y}[a > b]

วิธีอื่น (น่าเชื่อถือน้อยกว่า) แต่วิธีที่ง่ายกว่าคือการใช้งานandและorตัวดำเนินการ:

result = (a > b) and x or y

อย่างไรก็ตามสิ่งนี้จะไม่ทำงานหากxเป็นFalseเช่นนั้น

วิธีแก้ปัญหาที่เป็นไปได้คือการสร้างxและyแสดงรายการหรือสิ่งอันดับดังต่อไปนี้:

result = ((a > b) and [x] or [y])[0]

หรือ:

result = ((a > b) and (x,) or (y,))[0]

หากคุณทำงานกับพจนานุกรมแทนที่จะใช้เงื่อนไขแบบไตรภาคคุณสามารถใช้ประโยชน์จากget(key, default)ตัวอย่างเช่น:

shell = os.environ.get('SHELL', "/bin/sh")

แหล่งที่มา: ?: ใน Python ที่ Wikipedia


1
result = {1: x, 0: y}[a > b]เป็นอีกหนึ่งตัวแปรที่เป็นไปได้ ( TrueและFalseจริงแล้วเป็นจำนวนเต็มที่มีค่า1และ0)
วอลเตอร์ Tross

98

น่าเสียดายที่

(falseValue, trueValue)[test]

ทางออกไม่มีพฤติกรรมการลัดวงจร ดังนั้นทั้งสองfalseValueและtrueValueได้รับการประเมินโดยไม่คำนึงถึงเงื่อนไข นี่อาจเป็นสิ่งที่ไม่ดีหรือแม้กระทั่งบั๊กกี้ (เช่นทั้งสองtrueValueและfalseValueอาจเป็นวิธีการและมีผลข้างเคียง)

ทางออกหนึ่งสำหรับสิ่งนี้ก็คือ

(lambda: falseValue, lambda: trueValue)[test]()

(การดำเนินการล่าช้าจนกว่าผู้ชนะจะทราบ;)) แต่มันแนะนำความไม่สอดคล้องระหว่างวัตถุที่เรียกได้และไม่สามารถเรียกได้ นอกจากนี้ยังไม่สามารถแก้ปัญหากรณีใช้คุณสมบัติ

ดังนั้นการเล่าเรื่อง - การเลือกระหว่าง 3 โซลูชั่นที่กล่าวถึงคือการแลกเปลี่ยนระหว่างการมีคุณสมบัติลัดวงจรโดยใช้อย่างน้อยЗython 2.5 (IMHO ไม่ใช่ปัญหาอีกต่อไป) และไม่เสี่ยงต่อtrueValueข้อผิดพลาด" -evaluates-to-false" .


2
ในขณะที่ tuple of lambdas trick ใช้งานมันจะใช้เวลาประมาณ 3 เท่าของผู้ประกอบการที่สาม if else ifเป็นไปได้เท่านั้นที่จะเป็นความคิดที่เหมาะสมถ้ามันสามารถเปลี่ยนโซ่ยาวของ
Perkins

72

ผู้ประกอบการที่สามในภาษาการเขียนโปรแกรมที่แตกต่างกัน

ที่นี่ฉันเพียงแค่พยายามที่จะแสดงความแตกต่างที่สำคัญบางอย่างternary operatorระหว่างสองภาษาการเขียนโปรแกรม

ผู้ประกอบการที่ Ternary ใน Javascript

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

ผู้ประกอบการที่สามในทับทิม

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

ผู้ประกอบการที่สามใน Scala

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

ผู้ประกอบการที่สามในการเขียนโปรแกรม R

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

ผู้ประกอบการที่สามในงูหลาม

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0

14
นี้blogger พบผู้ประกอบ ternary หลามที่จะไม่จำเป็นที่แตกต่างจากภาษาอื่น
JamesThomasMoon1979

5
มันอาจฟังดูดื้อ; แต่สิ่งที่มันบอกว่าสำคัญก็คือมันเป็นไวยากรณ์ของ Python ที่คนที่ไม่เคยเห็นโอเปอร์เรเตอร์เข้าใจในขณะที่คนน้อยมากที่จะเข้าใจไวยากรณ์ที่ปกติมากกว่านี้เว้นแต่พวกเขาจะได้รับการบอกก่อน
fralau

1
Algol68: a = .if .true จากนั้น 1. อื่น ๆ 0 .fi สิ่งนี้อาจแสดงได้ด้วย = (. จริง. | 1 | 0) ตามปกติ Algol68 คือการปรับปรุงผู้สืบทอด
Albert van der Horst

63

สำหรับ Python 2.5 และใหม่กว่านั้นมีไวยากรณ์เฉพาะ:

[on_true] if [cond] else [on_false]

ใน Pythons รุ่นเก่าจะไม่มีการใช้ตัวดำเนินการแบบไตรภาค แต่สามารถจำลองได้

cond and on_true or on_false

แต่มีปัญหาที่อาจเกิดขึ้นซึ่งหากcondประเมินTrueและon_trueประเมินFalseแล้วจะถูกส่งกลับแทนon_false on_trueหากคุณต้องการพฤติกรรมนี้วิธีการก็ใช้ได้เช่นกัน:

{True: on_true, False: on_false}[cond is True] # is True, not == True

ซึ่งสามารถห่อโดย:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

และใช้วิธีนี้:

q(cond, on_true, on_false)

มันเข้ากันได้กับทุกรุ่นของหลาม


2
พฤติกรรมที่ไม่เหมือนกัน - q("blob", on_true, on_false)ผลตอบแทนon_falseในขณะที่ผลตอบแทนon_true if cond else on_false on_trueวิธีแก้ปัญหาคือการแทนที่condด้วยcond is not Noneในกรณีเหล่านี้แม้ว่าจะไม่ใช่วิธีที่สมบูรณ์แบบ

5
ทำไมไม่ลองbool(cond)แทนcond is Trueล่ะ อดีตตรวจสอบความจริงของcondหลังตรวจสอบตัวชี้ความเท่าเทียมกันกับTrueวัตถุ ตามที่ไฮไลต์โดย @AndrewCecil "blob"เป็นเรื่องจริง แต่ก็เป็นis not Trueจริง
Jonas Kölker

ว้าวมันดูแฮ็คจริงๆ! :) ในทางเทคนิคคุณสามารถเขียน[on_false, on_True][cond is True]เพื่อให้นิพจน์สั้นลง
Arseny

คำตอบนี้ไม่มีไฟฟ้าลัดวงจร หาก on_true และ on_false มีราคาแพงในการเรียกนี่เป็นคำตอบที่ไม่ดี
Hucker

44

คุณมักจะพบ

cond and on_true or on_false

แต่สิ่งนี้นำไปสู่ปัญหาเมื่อ on_true == 0

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

ที่คุณคาดหวังสำหรับผู้ประกอบการแบบไตรภาคปกติผลนี้

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1

38

Python มีตัวดำเนินการแบบเงื่อนไขหรือไม่

ใช่. จากไฟล์ไวยากรณ์ :

test: or_test ['if' or_test 'else' test] | lambdef

ส่วนที่น่าสนใจคือ:

or_test ['if' or_test 'else' test]

ดังนั้นการดำเนินการตามเงื่อนไขแบบไตรภาคจึงอยู่ในรูปแบบ:

expression1 if expression2 else expression3

expression3จะได้รับการประเมินอย่างเกียจคร้าน (นั่นคือประเมินเฉพาะในกรณีที่expression2เป็นเท็จในบริบทบูลีน) และเนื่องจากคำจำกัดความซ้ำคุณสามารถโยงพวกมันไปเรื่อย ๆ (แม้ว่ามันอาจจะถือว่าเป็นสไตล์ที่ไม่ดีก็ตาม)

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

หมายเหตุเกี่ยวกับการใช้งาน:

โปรดทราบว่าทุกคนจะต้องปฏิบัติตามที่มีif elseผู้ที่เรียนรู้รายการความเข้าใจและนิพจน์ตัวสร้างอาจเป็นบทเรียนที่ยากต่อการเรียนรู้ - สิ่งต่อไปนี้ใช้ไม่ได้เนื่องจาก Python คาดหวังว่านิพจน์ที่สามจะเป็นอย่างอื่น:

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

SyntaxError: invalid syntaxซึ่งก่อให้เกิด ดังนั้นข้างต้นเป็นทั้งชิ้นส่วนที่ไม่สมบูรณ์ของตรรกะ (บางทีผู้ใช้คาดหวังว่าไม่มี -op ในสภาพที่เป็นเท็จ) หรือสิ่งที่อาจจะมีวัตถุประสงค์เพื่อใช้ expression2 เป็นตัวกรอง - บันทึกว่าต่อไปนี้เป็น Python ที่ถูกกฎหมาย:

[expression1 for element in iterable if expression2]

expression2ทำงานเป็นตัวกรองสำหรับความเข้าใจในรายการและไม่ใช่ตัวดำเนินการแบบมีเงื่อนไข

ไวยากรณ์ทางเลือกสำหรับตัวพิมพ์เล็ก:

คุณอาจพบว่าค่อนข้างเจ็บปวดในการเขียนข้อความต่อไปนี้:

expression1 if expression1 else expression2

expression1จะต้องได้รับการประเมินสองครั้งด้วยการใช้งานด้านบน มันสามารถ จำกัด การซ้ำซ้อนหากมันเป็นเพียงตัวแปรท้องถิ่น อย่างไรก็ตาม Pythonic idiom ที่ใช้กันทั่วไปและมีประสิทธิภาพสำหรับกรณีการใช้งานนี้คือการใช้orพฤติกรรมการลัดของ:

expression1 or expression2

ซึ่งเทียบเท่าในความหมาย โปรดทราบว่าไกด์นำเที่ยวบางคนอาจ จำกัด การใช้งานนี้เนื่องจากมีความชัดเจน - มันบรรจุความหมายจำนวนมากไว้ในไวยากรณ์น้อยมาก


1
expression1 or expression2มีความคล้ายคลึงกันและมีข้อเสียเปรียบ / บวกเช่นเดียวกับexpression1 || expression2ใน javascript
JSDBroughton

1
ขอบคุณ @selurvedu - อาจทำให้เกิดความสับสนจนกว่าคุณจะได้ตรง ฉันเรียนรู้วิธีที่ยากลำบากดังนั้นวิธีการของคุณอาจไม่ยาก ;) การใช้ถ้าไม่มีอย่างอื่นในตอนท้ายของนิพจน์ตัวสร้างหรือรายการความเข้าใจจะกรอง iterable ด้านหน้ามันเป็นการทำงานแบบมีเงื่อนไขและต้องการสิ่งอื่น ไชโย !!
Aaron Hall

@AaronHall แม้ว่าการใช้ metasyntactic ของคุณexpressionNสำหรับทุกอินสแตนซ์จะสอดคล้องกัน แต่คุณอาจเข้าใจการตั้งชื่อได้ง่ายขึ้นซึ่งแยกแยะนิพจน์การทดสอบตามเงื่อนไขจากนิพจน์ผลลัพธ์สองรายการ เช่นresult1 if condition else result2. โดยเฉพาะอย่างยิ่งเมื่อทำรัง (หรือการผูกมัด):result1 if condition1 else result2 if condition2 else result3ผูกมัด): มาดูกันว่าวิธีนี้อ่านดีกว่ามากแค่ไหน?
tchrist

@tchrist ขอบคุณสำหรับการตรวจสอบ - หากคุณดูที่ประวัติการแก้ไขตอนนี้โพสต์นี้มีการแก้ไขสองครั้ง คำตอบอื่น ๆ ของฉันส่วนใหญ่โดยเฉพาะคำตอบยอดนิยมได้รับการทบทวนอีกครั้งแล้วครั้งเล่า คำตอบนี้ไม่เคยได้รับความสนใจของฉันเพราะสถานะของชุมชน wiki ไม่ได้ให้เครดิตฉันสำหรับเนื้อหาและดังนั้นฉันจึงไม่เห็นคะแนน เนื่องจากฉันไม่มีเวลาสำหรับการแก้ไขในตอนนี้กบจึงรู้ว่าเมื่อไรจะทำให้ฉันสนใจอีกในอนาคต ฉันสามารถเห็นว่าคุณได้แก้ไขคำตอบยอดนิยมดังนั้นอย่าลังเลที่จะยืม / พูดเนื้อหาของฉันจากโพสต์นี้ในที่นั้น (และอ้างถึงฉันถ้ามีข้อเสนอ!)
Aaron Hall

23

การจำลองผู้ประกอบการที่ประกอบไปด้วยหลาม

ตัวอย่างเช่น

a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()

เอาท์พุท:

'b greater than a'

ทำไมresult = (y, x)[a < b]คุณไม่ใช้lambdaฟังก์ชั่น?
Grijesh Chauhan

5
@GrijeshChauhan เพราะในการแสดงออก "compliated" เช่นเกี่ยวข้องกับการเรียกใช้ฟังก์ชั่น ฯลฯ สิ่งนี้จะถูกดำเนินการในทั้งสองกรณี สิ่งนี้อาจไม่ต้องการ
glglgl

20

ผู้ประกอบการเงื่อนไข Ternary เพียงแค่ช่วยให้การทดสอบเงื่อนไขในบรรทัดเดียวแทนที่ multiline ถ้าอื่นทำให้รหัสกะทัดรัด

ไวยากรณ์:

[on_true] ถ้า [expression] อื่น [on_false]

1- วิธีง่าย ๆ ในการใช้ผู้ประกอบการที่ประกอบไปด้วย:

# Program to demonstrate conditional operator
a, b = 10, 20
# Copy value of a in min if a < b else copy b
min = a if a < b else b
print(min)  # Output: 10

2- วิธีการโดยตรงของการใช้สิ่งอันดับ, พจนานุกรมและแลมบ์ดา:

# Python program to demonstrate ternary operator
a, b = 10, 20
# Use tuple for selecting an item
print( (b, a) [a < b] )
# Use Dictionary for selecting an item
print({True: a, False: b} [a < b])
# lamda is more efficient than above two methods
# because in lambda  we are assure that
# only one expression will be evaluated unlike in
# tuple and Dictionary
print((lambda: b, lambda: a)[a < b]()) # in output you should see three 10

3- ผู้ประกอบการที่สามสามารถเขียนเป็นซ้อนถ้าอื่น:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
print ("Both a and b are equal" if a == b else "a is greater than b"
        if a > b else "b is greater than a")

วิธีการดังกล่าวสามารถเขียนเป็น:

# Python program to demonstrate nested ternary operator
a, b = 10, 20
if a != b:
    if a > b:
        print("a is greater than b")
    else:
        print("b is greater than a")
else:
    print("Both a and b are equal") 
# Output: b is greater than a

1
โปรดทราบว่าผู้ประกอบการที่ประกอบไปด้วยน้อยกว่า (ในหน่วยความจำ) และเร็วกว่าซ้อนกันถ้า นอกจากนี้การซ้อนกันของคุณif-elseไม่ใช่การเขียนจริงของผู้ประกอบการที่ประกอบไปด้วยและจะสร้างผลลัพธ์ที่แตกต่างกันสำหรับค่าที่เลือกของ a และ b (โดยเฉพาะหากมีประเภทที่ใช้__ne__วิธีแปลก ๆ)
Perkins

19

คุณสามารถทำได้: -

[condition] and [expression_1] or [expression_2] ;

ตัวอย่าง:-

print(number%2 and "odd" or "even")

สิ่งนี้จะพิมพ์ "คี่" ถ้าจำนวนคี่หรือ "คู่" ถ้าจำนวนเป็นคู่


ผลลัพธ์: - หากเงื่อนไขเป็นจริง exp_1 จะถูกดำเนินการมิฉะนั้น exp_2 จะถูกดำเนินการ

บันทึก :- 0, None, False, emptylist, emptyString ประเมินว่าเป็นเท็จ และข้อมูลอื่นใดที่ไม่ใช่ 0 จะประเมินเป็น True

นี่คือวิธีการทำงาน:

หากเงื่อนไข [เงื่อนไข] กลายเป็น "จริง" ดังนั้น expression_1 จะได้รับการประเมิน แต่ไม่ใช่ expression_2 ถ้าเรา "และ" มีค่า 0 (ศูนย์) ผลลัพธ์จะเป็น fasle เสมอดังนั้นในคำสั่งด้านล่าง

0 and exp

นิพจน์ exp จะไม่ถูกประเมินเลยตั้งแต่ "และ" กับ 0 จะประเมินเป็นศูนย์เสมอและไม่จำเป็นต้องประเมินนิพจน์ นี่คือการทำงานของคอมไพเลอร์ในทุกภาษา

ใน

1 or exp

exp ของนิพจน์จะไม่ถูกประเมินเลยตั้งแต่ "หรือ" ด้วย 1 จะเป็น 1 เสมอดังนั้นมันจะไม่รบกวนการประเมินค่า exp ของ expression เนื่องจากผลลัพธ์จะเป็น 1 อย่างไรก็ตาม วิธีการปรับให้เหมาะสมของคอมไพเลอร์.

แต่ในกรณีของ

True and exp1 or exp2

การแสดงออกที่สอง exp2 จะไม่ถูกประเมินตั้งแต่ True and exp1จะเป็นจริงเมื่อ exp1 ไม่ใช่เท็จ

ในทำนองเดียวกันค่ะ

False and exp1 or exp2

นิพจน์ exp1 จะไม่ถูกประเมินเนื่องจาก False เทียบเท่ากับการเขียน 0 และการทำ "และ" ด้วย 0 จะเป็น 0 เอง แต่หลังจาก exp1 ตั้งแต่ "หรือ" ถูกใช้งานมันจะประเมินนิพจน์ exp2 หลัง "หรือ"


หมายเหตุ: -การแยกประเภทนี้โดยใช้ "หรือ" และ "และ" และ "สามารถใช้ได้เฉพาะเมื่อ expression_1 ไม่มีค่าความจริงเป็นเท็จ (หรือ 0 หรือไม่มีหรือ emptylist [] หรือ emptystring '') เนื่องจากถ้า expression_1 กลายเป็น เท็จจากนั้น expression_2 จะถูกประเมินเนื่องจากการมีอยู่ "หรือ" ระหว่าง exp_1 และ exp_2

ในกรณีที่คุณยังต้องการให้มันทำงานได้กับทุกกรณีโดยไม่คำนึงว่า exp_1 และ exp_2 คืออะไรให้ทำดังนี้: -

[condition] and ([expression_1] or 1) or [expression_2] ;


หากคุณต้องการที่จะใช้ในบริบทของx = [condition] and ([expression_1] or 1) or [expression_2]และexpression_1ประเมินเป็นเท็จxจะไม่1 expression_1ใช้คำตอบที่ยอมรับได้
moi

18

เคล็ดลับมากกว่าคำตอบ (ไม่จำเป็นต้องทำซ้ำอย่างชัดเจนสำหรับเวลา hundreth) แต่บางครั้งฉันใช้มันเป็นทางลัด oneliner ในโครงสร้าง:

if conditionX:
    print('yes')
else:
    print('nah')

, กลายเป็น:

print('yes') if conditionX else print('nah')

บางคน (หลายคน :) อาจขมวดคิ้วว่ามันเป็นเสียงที่ไม่ไพเราะ (แม้กระทั่ง ruby-ish :) แต่ฉันเองก็พบว่ามันเป็นธรรมชาติมากกว่า - นั่นคือวิธีที่คุณแสดงมันตามปกติบวกกับการดึงดูดสายตาเล็กน้อยในโค้ดขนาดใหญ่


5
ฉันชอบprint( 'yes' if conditionX else 'nah' )คำตอบของคุณมากกว่า :-)
frederick99

นั่นคือถ้าคุณต้องการprint()ในทั้งสองกรณี - และมันก็ดูไพเราะมากกว่านี้ฉันต้องยอมรับ :) แต่ถ้าการแสดงออก / ฟังก์ชั่นไม่เหมือนกัน - เหมือนprint('yes') if conditionX else True- เพื่อให้ได้ความจริงprint()เท่านั้นconditionX
Todor Minakov

หากต้องการเพิ่มคำพูดของ Frederick99 อีกเหตุผลหนึ่งที่ต้องหลีกเลี่ยงprint('yes') if conditionX else print('nah')คือการให้ SyntaxError ใน Python2
Thierry Lathuille

เหตุผลเดียวที่จะช่วยให้เกิดข้อผิดพลาดทางไวยากรณ์เป็นเพราะในหลาม 2 พิมพ์คำสั่ง - print "yes"ในขณะที่งูใหญ่ 3 มันเป็นฟังก์ชั่น print("yes")- ที่สามารถแก้ไขได้โดยการอย่างใดอย่างหนึ่งใช้มันเป็นคำสั่งหรือดีกว่า from future import print_function-
Todor Minakov

18
a if condition else b

เพียงจำปิรามิดนี้หากคุณมีปัญหาในการจดจำ:

     condition
  if           else
a                   b 

14

ทางเลือกหนึ่งในการแสดงออกตามเงื่อนไขของ Python

"yes" if boolean else "no"

คือต่อไปนี้:

{True:"yes", False:"no"}[boolean]

ซึ่งมีส่วนขยายที่ดีดังต่อไปนี้:

{True:"yes", False:"no", None:"maybe"}[boolean_or_none]

ทางเลือกที่สั้นที่สุดยังคงอยู่:

("no", "yes")[boolean]

แต่ไม่มีทางเลือกอื่น

yes() if boolean else no()

หากคุณต้องการหลีกเลี่ยงการประเมินผลyes() และ no()เพราะใน

(no(), yes())[boolean]  # bad

ทั้งno()และyes()ได้รับการประเมิน


10

ภาษาการเขียนโปรแกรมจำนวนมากที่ได้มาจากCมักจะมีไวยากรณ์ต่อไปนี้ของผู้ประกอบการเงื่อนไขที่ประกอบไปด้วย:

<condition> ? <expression1> : <expression2>

ตอนแรกPython B enevolent D ictator FหรือL ife (ผมหมายถึงกุยรถตู้ซัมของหลักสูตร) ปฏิเสธมัน (ในฐานะที่ไม่ใช่ Pythonic สไตล์) เพราะมันค่อนข้างยากที่จะเข้าใจสำหรับคนที่ไม่ได้ใช้Cภาษา นอกจากนี้เครื่องหมายโคลอน:นั้นมีประโยชน์หลายอย่างอยู่Pythonแล้ว หลังจากPEP 308ได้รับการอนุมัติPythonในที่สุดก็ได้รับการแสดงออกทางลัดตามเงื่อนไขของตัวเอง (สิ่งที่เราใช้ตอนนี้):

<expression1> if <condition> else <expression2>

ดังนั้นก่อนอื่นประเมินสภาพ ถ้ามันกลับTrue, Expression1จะได้รับการประเมินเพื่อให้ผลลัพธ์ที่มิฉะนั้นExpression2จะถูกประเมิน เนื่องจากกลไกการประเมินผลของ Lazy - นิพจน์เดียวเท่านั้นที่จะถูกดำเนินการ

นี่คือตัวอย่าง (เงื่อนไขจะถูกประเมินจากซ้ายไปขวา):

pressure = 10
print('High' if pressure < 20 else 'Critical')

# Result is 'High'

ผู้ประกอบการ Ternary สามารถถูกผูกมัดในซีรีส์:

pressure = 5
print('Normal' if pressure < 10 else 'High' if pressure < 20 else 'Critical')

# Result is 'Normal'

อันต่อไปนี้เหมือนกับอันก่อนหน้านี้:

pressure = 5

if pressure < 20:
    if pressure < 10:
        print('Normal')
    else:
        print('High')
else:
    print('Critical')

# Result is 'Normal'

หวังว่านี่จะช่วยได้


10

ตามที่ได้ตอบไปแล้วใช่มีตัวดำเนินการที่ประกอบไปด้วยในหลาม:

<expression 1> if <condition> else <expression 2>

ข้อมูลเพิ่มเติม:

หาก<expression 1>เป็นเงื่อนไขที่คุณสามารถใช้การประเมิน Short-cirquit :

a = True
b = False

# Instead of this:
x = a if a else b

# You could use Short-cirquit evaluation:
x = a or b

PS: แน่นอนการประเมินระยะสั้นของไซริคไม่ใช่ผู้ประกอบการที่สาม แต่บ่อยครั้งที่ผู้ประกอบการที่ใช้ในกรณีที่ไฟฟ้าลัดวงจรจะเพียงพอ


1
โหวตขึ้นสำหรับshort-circuitการประเมินผลนั้น
CodeIt

7

ใช่หลามมีผู้ประกอบการที่สามนี่คือไวยากรณ์และรหัสตัวอย่างเพื่อแสดงให้เห็นถึงเดียวกัน :)

#[On true] if [expression] else[On false]
# if the expression evaluates to true then it will pass On true otherwise On false


a= input("Enter the First Number ")
b= input("Enter the Second Number ")

print("A is Bigger") if a>b else print("B is Bigger")

ฉันได้เพิ่มตัวอย่างประโยคคำสั่งหนึ่งบรรทัดเพื่อตรวจสอบว่าหมายเลขใดมีขนาดใหญ่ที่จะอธิบายเพิ่มเติมต่อไป
PythonLover

1
printไม่ใช่ตัวเลือกที่ดีจริงๆเพราะจะให้ SyntaxError ใน Python2
Thierry Lathuille

@Thierry Lathuille ที่นี่ฉันใช้ print () ฟังก์ชั่นไม่พิมพ์คำสั่งฟังก์ชั่นการพิมพ์สำหรับ Python 3 ในขณะที่คำสั่งพิมพ์สำหรับ Python 2
PythonLover

คำถามได้ถูกถามใน SO แล้วให้ลองกับ Python 2 แล้วคุณจะเห็นเอง 'print (' hello ') เป็นรูปแบบที่ถูกต้องสมบูรณ์ใน Python 2.7 แต่วิธีการแยกวิเคราะห์ทำให้โค้ดของคุณด้านบนโยน SyntaxError
Thierry Lathuille

2

Python มีรูปแบบที่สามสำหรับการมอบหมาย; อย่างไรก็ตามอาจมีรูปแบบที่สั้นกว่าที่ผู้คนควรระวัง

เป็นเรื่องปกติที่จะต้องกำหนดให้กับตัวแปรหนึ่งค่าหรืออีกค่าหนึ่งขึ้นอยู่กับเงื่อนไข

>>> li1 = None
>>> li2 = [1, 2, 3]
>>> 
>>> if li1:
...     a = li1
... else:
...     a = li2
...     
>>> a
[1, 2, 3]

^ นี่เป็นรูปแบบยาวสำหรับการทำงานที่ได้รับมอบหมาย

ด้านล่างเป็นรูปแบบที่ประกอบไปด้วย แต่นี่ไม่ใช่วิธีที่รวบรัดที่สุด - ดูตัวอย่างสุดท้าย

>>> a = li1 if li1 else li2
>>> 
>>> a
[1, 2, 3]
>>> 

ด้วย Python คุณสามารถใช้orสำหรับการมอบหมายอื่น

>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

การทำงานดังกล่าวข้างต้นli1เป็นเพราะNoneและ interp ถือว่าเป็นเท็จในการแสดงออกทางตรรกะ จากนั้น interp จะดำเนินการต่อและประเมินค่านิพจน์ที่สองซึ่งไม่ใช่Noneและไม่ใช่รายการที่ว่างเปล่าดังนั้นจึงได้รับการกำหนดให้

ใช้ได้กับรายการที่ว่างเปล่า ตัวอย่างเช่นหากคุณต้องการกำหนดaรายการใดก็ตามที่มีรายการ

>>> li1 = []
>>> li2 = [1, 2, 3]
>>> 
>>> a = li1 or li2
>>> 
>>> a
[1, 2, 3]
>>> 

เมื่อรู้สิ่งนี้คุณสามารถมอบหมายสิ่งเหล่านี้ได้ทุกเมื่อที่พบ นอกจากนี้ยังใช้งานได้กับสตริงและ iterables อื่น ๆ คุณสามารถกำหนดaสตริงใดก็ได้ที่ไม่ว่างเปล่า

>>> s1 = ''
>>> s2 = 'hello world'
>>> 
>>> a = s1 or s2
>>> 
>>> a
'hello world'
>>> 

ฉันชอบไวยากรณ์ T ของ Ternary เสมอ แต่ Python จะก้าวไปอีกขั้น!

ฉันเข้าใจว่าบางคนอาจพูดว่านี่ไม่ใช่ตัวเลือกโวหารที่ดีเพราะต้องอาศัยกลไกที่ไม่ชัดเจนสำหรับนักพัฒนาทั้งหมดทันที ฉันไม่เห็นด้วยกับมุมมองนั้น Python เป็นภาษาที่มีรูปแบบหลากหลายและมีอุบายทางอุทานมากมาย แต่ยิ่งคุณเรียนรู้และเข้าใจกลไกของระบบพื้นฐานมากเท่าไหร่คุณก็ยิ่งชื่นชมมันมากขึ้นเท่านั้น


1

คำตอบอื่น ๆ พูดคุยอย่างถูกต้องเกี่ยวกับตัวดำเนินการแบบไตรภาค ฉันต้องการที่จะเติมเต็มโดยการกล่าวถึงสถานการณ์ที่ผู้ประกอบการที่สามมักจะใช้ แต่ที่มีสำนวนที่ดีกว่า นี่คือสถานการณ์ของการใช้ค่าเริ่มต้น

สมมติว่าเราต้องการใช้option_valueกับค่าเริ่มต้นหากยังไม่ได้ตั้ง:

run_algorithm(option_value if option_value is not None else 10)

หรือเพียงแค่

run_algorithm(option_value if option_value else 10)

อย่างไรก็ตามทางออกที่ดีกว่าก็คือการเขียน

run_algorithm(option_value or 10)

-2

หากมีการกำหนดตัวแปรและคุณต้องการตรวจสอบว่ามีค่าที่คุณสามารถทำได้ a or b

def test(myvar=None):
    # shorter than: print myvar if myvar else "no Input"
    print myvar or "no Input"

test()
test([])
test(False)
test('hello')
test(['Hello'])
test(True)

จะส่งออก

no Input
no Input
no Input
hello
['Hello']
True

1
ในขณะที่มีประโยชน์สำหรับปัญหาที่คล้ายกันนี้ไม่ได้เป็นเงื่อนไขที่ประกอบไปด้วยสาม มันทำงานเพื่อแทนที่แต่ไม่x if x else y x if z else y
Perkins

-2

วิธีที่เป็นระเบียบเพื่อเชื่อมโยงตัวดำเนินการหลายตัว

f = lambda x,y: 'greater' if x > y else 'less' if y > x else 'equal'

array = [(0,0),(0,1),(1,0),(1,1)]

for a in array:
  x, y = a[0], a[1]
  print(f(x,y))

# Output is:
#   equal,
#   less,
#   greater,
#   equal

-2

ฉันพบว่ายุ่งยากกับ python ไวยากรณ์เริ่มต้นval = a if cond else bดังนั้นบางครั้งฉันทำสิ่งนี้:

iif = lambda (cond, a, b): a if cond else b
# so I can then use it like:
val = iif(cond, a, b)

แน่นอนว่ามันมีข้อเสียของการประเมินทั้งสองด้าน (a และ b) เสมอ แต่ไวยากรณ์มันชัดเจนกว่าสำหรับฉัน


ดูเหมือนว่าจะมีปริมาณงานเพิ่มขึ้นเป็นสองเท่าของการใช้งาน RAM มากกว่าและสับสนกว่าval = a if cond else bคำสั่งที่ง่ายกว่า
eatsfood

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.