การใส่คำสั่ง if-elif-else ในบรรทัดเดียว?


125

ฉันได้อ่านลิงก์ด้านล่าง แต่ไม่สามารถตอบคำถามของฉันได้
Python มีตัวดำเนินการที่มีเงื่อนไขแบบ ternary หรือไม่ (คำถามเกี่ยวกับการควบแน่นคำสั่ง if-else เป็นบรรทัดเดียว)

มีวิธีที่ง่ายกว่าในการเขียนคำสั่ง if-elif-else เพื่อให้พอดีกับบรรทัดเดียวหรือไม่?
ตัวอย่างเช่น,

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

หรือตัวอย่างในโลกแห่งความเป็นจริง:

if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

ฉันแค่รู้สึกว่าถ้าตัวอย่างข้างต้นสามารถเขียนได้ด้วยวิธีต่อไปนี้มันจะดูกระชับมากขึ้น

x=2 if i>100 elif i<100 1 else 0 [WRONG]

คำตอบ:


186

ไม่เป็นไปไม่ได้ (อย่างน้อยก็ไม่ใช่ด้วยคำสั่งตามอำเภอใจ) และไม่เป็นที่ต้องการ การติดตั้งทุกอย่างในบรรทัดเดียวมักจะละเมิดPEP-8โดยมีข้อบังคับว่าบรรทัดต้องมีความยาวไม่เกิน 80 อักขระ

นอกจากนี้ยังต่อต้าน Zen of Python: "Readability counts" (พิมพ์import thisที่พรอมต์ Python เพื่ออ่านข้อมูลทั้งหมด)

คุณสามารถใช้นิพจน์ ternary ใน Python ได้ แต่สำหรับนิพจน์เท่านั้นไม่ใช่สำหรับคำสั่ง:

>>> a = "Hello" if foo() else "Goodbye"

แก้ไข:

คำถามที่แก้ไขแล้วของคุณแสดงให้เห็นว่าทั้งสามคำสั่งเหมือนกันยกเว้นค่าที่กำหนด ในกรณีนั้นตัวดำเนินการที่ถูกล่ามโซ่ใช้งานได้ แต่ฉันยังคิดว่ามันอ่านได้น้อยลง:

>>> i=100
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
0
>>> i=101
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
2
>>> i=99
>>> a = 1 if i<100 else 2 if i>100 else 0
>>> a
1

เหตุใดนิพจน์ที่สองจึงไม่คืนค่า 0 ฉันสูงกว่า 100
AstralWolf

6
@AstralWolf: ขอบคุณมาก! สิ่งนี้แสดงให้เห็นถึงจุดที่ฉันพยายามทำอย่างสมบูรณ์แบบ - การแสดงออกที่ถูกล่ามโซ่เป็นไปได้ แต่อ่านได้น้อยกว่าและเข้าใจผิดได้ง่ายอย่างเห็นได้ชัด
Tim Pietzcker

1
หากคุณต้องการให้อ่านง่ายขึ้นคุณสามารถใส่วงเล็บไว้รอบ ๆ ได้ดังนี้: a = 1 if i < 100 else (2 if i > 100 else 0)(ยังไม่ทดสอบ แต่ฉันคิดว่าน่าจะใช้ได้)
Zac

@TimPietzcker คุณจะอธิบายความแตกต่างระหว่างนิพจน์และข้อความได้อย่างไร?
AsheKetchum

62

หากคุณต้องการเพียงการแสดงออกที่แตกต่างกันสำหรับกรณีที่แตกต่างกันสิ่งนี้อาจเหมาะสำหรับคุณ:

expr1 if condition1 else expr2 if condition2 else expr

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

a = "neg" if b<0 else "pos" if b>0 else "zero"

1
"pos"คือไม่ได้คำสั่งก็แสดงออก
Tim Pietzcker

@TimPietzcker ขอบคุณฉันปรับปรุงโพสต์ให้ถูกต้องมากขึ้น
Lycha

20

เพียงซ้อนคำสั่ง if อื่นในคำสั่ง else แต่นั่นไม่ได้ทำให้ดูสวยขึ้น แต่อย่างใด

>>> x=5
>>> x if x>0 else ("zero" if x==0 else "invalid value")
5
>>> x = 0
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'zero'
>>> x = -1
>>> x if x>0 else ("zero" if x==0 else "invalid value")
'invalid value'

1
สำหรับฉันสิ่งนี้อ่านได้ง่ายกว่าคำตอบที่ยอมรับเพราะยังคงรักษาโครงสร้างและแนวคิดของประโยคแรก เป็นเพียงเรื่องส่วนตัว
Ezarate11

12

แม้จะมีคำตอบอื่น ๆ : ใช่เป็นไปได้ :

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

แปลเป็นซับเดียวต่อไปนี้:

statement1 if expression1 else (statement2 if expression2 else statement3)

ในความเป็นจริงคุณสามารถทำรังเหล่านั้นได้จนถึงระยะอนันต์ สนุก ;)


แล้วเวลาที่ถ่ายล่ะ? สิ่งที่ฉันคิดว่าการวนซ้ำเหล่านี้จะใช้เวลานานกว่ามาก ดังนั้นจะมีทางเลือกอื่นแทนการวนซ้ำเพื่อเพิ่มความเร็วในการบริโภค
loveR

สวัสดี @loveR นี่ไม่ใช่การวนซ้ำมันเป็นเพียงคำสั่งที่ซ้อนกันหากเป็นอย่างอื่นและด้วยเวลาเล็กน้อย
gustavz

7

คุณสามารถเลือกใช้getวิธีการของdict:

x = {i<100: -1, -10<=i<=10: 0, i>100: 1}.get(True, 2)

คุณไม่จำเป็นต้องใช้getวิธีการนี้หากรับประกันว่าคีย์ใดคีย์หนึ่งจะประเมินเป็นTrue:

x = {i<0: -1, i==0: 0, i>0: 1}[True]

คีย์ส่วนใหญ่ควรประเมินเป็นอย่างดี Trueอย่างดี หากมีการประเมินมากกว่าหนึ่งคีย์Trueผลลัพธ์อาจดูเหมือนไม่สามารถคาดเดาได้


6

มีทางเลือกอื่นที่ค่อนข้างอ่านไม่ออกในความคิดของฉัน แต่ฉันจะแบ่งปันตามความอยากรู้:

x = (i>100 and 2) or (i<100 and 1) or 0

ข้อมูลเพิ่มเติมที่นี่: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not


2
ดูเหมือนว่าจาวาสคริปต์บัญญัติ ;-)
Ant6n

4
if i > 100:
    x = 2
elif i < 100:
    x = 1
else:
    x = 0

หากคุณต้องการใช้รหัสดังกล่าวข้างต้นในหนึ่งบรรทัดคุณสามารถใช้สิ่งต่อไปนี้:

x = 2 if i > 100 else 1 if i < 100 else 0

ในการทำเช่นนั้น x จะถูกกำหนด 2 ถ้า i> 100, 1 ถ้า i <100 และ 0 ถ้า i = 100


3

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

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

สิ่งที่ต้องการ:

def save(): 
   ...
def edit():
   ...
options = {"save": save, "edit": edit, "remove": lambda : "Not Implemented"}

option = get_input()
result = options[option]()

แทนที่จะเป็น if-else:

if option=="save":
    save()
...

2

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

x = 2*(i>100) | 1*(i<100)

การเปรียบเทียบจะเป็นจริงหรือเท็จและเมื่อคูณกับตัวเลขจะเป็น 1 หรือ 0 สามารถใช้ a + แทน | ระหว่างกลาง.


1

ตัวดำเนินการ ternaryเป็นวิธีที่ดีที่สุดในการแสดงออกที่กระชับ ไวยากรณ์คือvariable = value_1 if condition else value_2. ดังนั้นตัวอย่างของคุณคุณต้องใช้ตัวดำเนินการ ternary สองครั้ง:

i = 23 # set any value for i
x = 2 if i > 100 else 1 if i < 100 else 0

0

คุณสามารถใช้คำสั่ง ternary if ที่ซ้อนกันได้

# if-else ternary construct
country_code = 'USA'
is_USA = True if country_code == 'USA' else False
print('is_USA:', is_USA)

# if-elif-else ternary construct
# Create function to avoid repeating code.
def get_age_category_name(age):
    age_category_name = 'Young' if age <= 40 else ('Middle Aged' if age > 40 and age <= 65 else 'Senior')
    return age_category_name

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