Đặt câu lệnh if-elif-else trên một dòng?


123

Tôi đã đọc các liên kết bên dưới, nhưng nó không giải quyết được câu hỏi của tôi.
Python có toán tử điều kiện bậc ba không? (câu hỏi là về việc cô đọng câu lệnh if-else thành một dòng)

Có cách nào dễ dàng hơn để viết câu lệnh if-elif-else để nó nằm gọn trên một dòng không?
Ví dụ,

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

Hoặc một ví dụ trong thế giới thực:

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

Tôi chỉ cảm thấy nếu ví dụ trên có thể được viết theo cách sau, nó có thể trông ngắn gọn hơn.

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

Câu trả lời:


183

Không, điều đó là không thể (ít nhất là không phải với các tuyên bố tùy tiện), và cũng không phải là mong muốn. Việc sắp xếp mọi thứ trên một dòng rất có thể sẽ vi phạm PEP-8 trong đó bắt buộc các dòng không được dài quá 80 ký tự.

Nó cũng chống lại Zen của Python: "Số lượng khả năng đọc". (Nhập import thisvào lời nhắc Python để đọc toàn bộ).

Bạn có thể sử dụng một biểu thức bậc ba trong Python, nhưng chỉ cho các biểu thức, không cho các câu lệnh:

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

Biên tập:

Câu hỏi sửa đổi của bạn bây giờ cho thấy rằng ba câu lệnh giống hệt nhau ngoại trừ giá trị được gán. Trong trường hợp đó, một toán tử bậc ba được xâu chuỗi hoạt động, nhưng tôi vẫn nghĩ rằng nó ít đọc hơn:

>>> 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

Tại sao biểu thức thứ hai không trả về 0? i là trên 100
AstralWolf

6
@AstralWolf: Cảm ơn bạn rất nhiều! Điều này minh họa hoàn hảo quan điểm mà tôi đang cố gắng đưa ra - một biểu thức chuỗi ba chữ có thể được thực hiện nhưng ít dễ đọc hơn và rõ ràng là dễ hiểu nhầm.
Tim Pietzcker

1
Nếu bạn cần nó để có thể đọc nhiều hơn, bạn có thể đặt dấu ngoặc xung quanh nó, như thế này: a = 1 if i < 100 else (2 if i > 100 else 0)(chưa được kiểm tra, nhưng tôi nghĩ rằng nó sẽ làm việc)
Zac

@TimPietzcker, bạn sẽ mô tả sự khác biệt giữa biểu thức và câu lệnh như thế nào?
AsheKetchum

62

Nếu bạn chỉ cần các biểu thức khác nhau cho các trường hợp khác nhau thì điều này có thể phù hợp với bạn:

expr1 if condition1 else expr2 if condition2 else expr

Ví dụ:

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

1
"pos"không một tuyên bố, nó là một biểu hiện.
Tim Pietzcker 25/12/12

@TimPietzcker Thank's, mình đã cập nhật bài để chính xác hơn.
Lycha 25/12/12

20

Chỉ cần lồng mệnh đề if khác trong câu lệnh else. Nhưng điều đó không làm cho nó trông đẹp hơn chút nào.

>>> 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
Đối với tôi, điều này dễ đọc hơn nhiều so với câu trả lời được chấp nhận vì nó duy trì cấu trúc và khái niệm của mệnh đề đầu tiên; chỉ là vấn đề chủ quan.
Ezarate11

11

Mặc dù một số câu trả lời khác: CÓ, nó có thể :

if expression1:
   statement1
elif expression2:
   statement2
else:
   statement3

dịch sang một lớp lót sau:

statement1 if expression1 else (statement2 if expression2 else statement3)

trong thực tế, bạn có thể lồng chúng cho đến vô tận. Thưởng thức ;)


làm thế nào về thời gian thực hiện? những gì tôi cho rằng, những vòng lặp muti này sẽ tốn thời gian hơn nhiều. vì vậy có thể có một giải pháp thay thế cho các vòng lặp lồng nhau, để có tốc độ tiêu thụ tốt hơn.
loveR

xin chào @loveR, đây không phải là vòng lặp, nó chỉ là một câu lệnh if else lồng nhau và trong thời gian không đáng kể
gustavz

7

Bạn có thể tùy ý sử dụng getphương pháp của một dict:

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

Bạn không cần getphương pháp này nếu một trong các khóa được đảm bảo để đánh giá True:

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

Lý tưởng nhất là một trong các khóa nên đánh giá True. Nếu có nhiều hơn một khóa đánh giá True, kết quả có thể không thể đoán trước được.



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

Nếu bạn muốn sử dụng mã được đề cập ở trên trong một dòng, bạn có thể sử dụng như sau:

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

Khi làm như vậy, x sẽ được gán 2 nếu i> 100, 1 nếu i <100 và 0 nếu i = 100


3

Nó cũng phụ thuộc vào bản chất của các biểu hiện của bạn. Lời khuyên chung cho các câu trả lời khác của "không làm điều đó" là khá hợp lệ cho các tuyên bố chung chung và biểu thức chung chung.

Nhưng nếu tất cả những gì bạn cần là một bảng "điều phối", chẳng hạn như gọi một hàm khác tùy thuộc vào giá trị của một tùy chọn nhất định, bạn có thể đặt các hàm để gọi bên trong từ điển.

Cái gì đó như:

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

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

Thay vì if-else:

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

2

Mọi người đã đề cập đến biểu thức bậc ba. Đôi khi với một phép gán có điều kiện đơn giản như ví dụ của bạn, bạn có thể sử dụng một biểu thức toán học để thực hiện phép gán có điều kiện. Điều này có thể không làm cho mã của bạn dễ đọc, nhưng nó đưa nó vào một dòng khá ngắn. Ví dụ của bạn có thể được viết như thế này:

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

Các phép so sánh sẽ là Đúng hoặc Sai, và khi nhân với các số sẽ là 1 hoặc 0. Người ta có thể sử dụng dấu + thay cho dấu | ở giữa.


1

Các nhà điều hành ternary là cách tốt nhất để một biểu thức súc tích. Cú pháp là variable = value_1 if condition else value_2. Vì vậy, với ví dụ của bạn, bạn phải áp dụng toán tử bậc ba hai lần:

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

0

Bạn có thể sử dụng các câu lệnh if bậc ba lồng nhau.

# 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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.