2010-09-16 14 views
6

Tôi đã có một hàm trả về một thành viên ngẫu nhiên của một số nhóm theo thứ tự ưu tiên. Nó đã đi một cái gì đó như thế này:Có một lựa chọn thay thế nào cho `ngoại trừ: pass` không?

def get_random_foo_or_bar(): 
    "I'd rather have a foo than a bar." 

    if there_are_foos(): 
     return get_random_foo() 

    if there_are_bars(): 
     return get_random_bar() 

    raise IndexError, "No foos, no bars" 

Tuy nhiên, điều đầu tiên get_random_foo làm là xác minh có foos và nâng cao một IndexError nếu không muốn nói, vì vậy there_are_foos là không cần thiết. Hơn nữa, một cơ sở dữ liệu có liên quan và sử dụng các hàm riêng biệt tạo ra một vấn đề đồng thời. Theo đó, tôi viết lại nó một cái gì đó như thế này:

def get_random_foo_or_bar(): 
    "Still prefer foos." 

    try: 
     return get_random_foo() 
    except IndexError: 
     pass 

    try: 
     return get_random_bar() 
    except IndexError: 
     pass 

    raise IndexError, "No foos, no bars" 

Nhưng tôi tìm thấy điều này ít nhiều có thể đọc được, và như tôi đã không bao giờ có lý do để sử dụng pass trước khi nó cảm thấy instictively sai.

Có mẫu hình hiệu quả hơn hay tôi nên học cách chấp nhận pass?

Lưu ý: Tôi muốn tránh bất kỳ tổ nào vì các loại khác có thể được thêm vào sau.


Sửa

Cảm ơn tất cả những ai nói rằng pass là tốt - đó là yên tâm!

Cũng nhờ những người đề xuất thay thế ngoại lệ với giá trị trả lại là None. Tôi có thể thấy đây là một mô hình hữu ích như thế nào, nhưng tôi cho rằng đó là sai ngữ nghĩa trong tình huống này: các chức năng đã được yêu cầu thực hiện một nhiệm vụ bất khả thi để họ phải đưa ra một ngoại lệ. Tôi thích theo dõi hành vi của mô-đun random (ví dụ: random.choice([])).

+1

Việc sử dụng trong 'báo cáo except' có lẽ là việc sử dụng phổ biến nhất của' pass' bằng Python. Vì vậy, tôi sẽ quen với nó. –

+0

"Nhưng tôi thấy điều này ít dễ đọc hơn ... nó cảm thấy sai lầm một cách vô lý" - nghĩ về nó như một vấn đề văn hóa. Nó có vẻ lạ, nhưng đó là cách sạch nhất để sử dụng ngôn ngữ. – detly

Trả lời

13

Đó chính xác là cách tôi viết. Nó đơn giản và nó có ý nghĩa. Tôi thấy không có vấn đề gì với câu lệnh pass.

Nếu bạn muốn giảm sự lặp lại và dự đoán thêm các loại trong tương lai, bạn có thể cuộn vòng này thành vòng lặp. Sau đó, bạn có thể thay đổi pass đến một continue tuyên bố về mặt chức năng tương đương, nếu đó là dễ chịu hơn cho mắt của bạn:

for getter in (get_random_foo, get_random_bar): 
    try: 
     return getter() 
    except IndexError: 
     continue # Ignore the exception and try the next type. 

raise IndexError, "No foos, no bars" 
1

Nếu nó chỉ là hai, có thể lúc nào cũng chỉ ...

try: 
    return get_random_foo() 
except IndexError: 
    try: 
     return get_random_bar() 
    except IndexError: 
     raise IndexError, "No foos, no bars" 

Nếu đó là nhiều hơn hai, những gì bạn đã viết dường như hoàn toàn chấp nhận được.

2

pass là tốt (có một lý do nó trong ngôn ngữ -!), Nhưng một pass- thay thế miễn phí chỉ mất hơn một chút làm tổ:

try: return get_random_foo() 
except IndexError: 
    try: return get_random_bar() 
    except IndexError: 
     raise IndexError "no foos, no bars" 

Python của Zen (import this từ dấu nhắc thông dịch viên tương tác) nói "phẳng là tốt hơn so với lồng", nhưng làm tổ là cũng trong ngày ngôn ngữ điện tử, để bạn có thể sử dụng khi bạn quyết định (có lẽ là chứng ngộ) mà bạn có thể làm tốt hơn con người khôn ngoan đó! -) (Như trong, "nếu bạn gặp Đức Phật trên đường" ...).

2

Có vẻ hơi lạ đối với tôi rằng get_random_foo() đang tăng chỉ số IndexError khi nó không lấy chỉ mục làm tham số (nhưng có thể có ý nghĩa hơn trong ngữ cảnh). Tại sao không có get_random_foo() hoặc trình bao bọc, hãy bắt lỗi và trả lại Không có gì thay thế?

def get_random_foo_wrapper(): 
    try: 
     return get_random_foo() 
    except IndexError: 
     return None 

def get_random_foo_or_bar(): 
    "I'd rather have a foo than a bar." 

    return get_random_foo_wrapper() or get_random_bar_wrapper() or None 

Sửa: Tôi nên đề cập đến rằng nếu foo & thanh là những đối tượng có thể đánh giá là False (0 hoặc '' nói) sau đó so sánh or sẽ bỏ qua chúng mà là BAD

+0

Tôi lấy tín hiệu từ mô-đun ngẫu nhiên - thử chạy 'random.choice ([])'. Mặc dù giải pháp thú vị, cảm ơn! –

0

Xây dựng trên Lời đề nghị của Peter Gibson, bạn có thể tạo ra một hàm bao hàm chung mà nuốt một ngoại lệ nhất định. Và sau đó bạn có thể viết hàm trả về một trình bao bọc chung chung cho một ngoại lệ được cung cấp. Hoặc heck, cho một danh sách được cung cấp ngoại lệ.

def maketrap(*exceptions): 
    def trap(func, *args, **kwargs): 
     try: 
      return func(*args, **kwargs) 
     except exceptions: 
      return None 
    return trap 

def get_random_foo_or_bar(): 
    mytrap = maketrap(IndexError) 
    return mytrap(get_random_foo) or mytrap(get_random_bar) or None 
0

Nếu bạn không thực sự cần được thông báo ngoại lệ (chỉ loại):

def get_random_foo_or_bar(): 
    try: 
     return get_random_foo() 
    except IndexError: 
     return get_random_bar() # if failing at this point, 
            # the whole function will raise IndexError 
+0

Tôi nghĩ rằng tôi muốn nâng cao lỗi một cách rõ ràng từ 'get_random_foo_or_bar' thay vì dựa vào lỗi xảy ra là giống nhau và cần nhận xét. Ngoài ra, cho phép tôi trả về một thông báo ngoại lệ thích hợp từ 'get_random_foo_or_bar'. –

0

Có cần thiết mà get_random_foo/bar() nâng cao một IndexError nếu nó không thể thành công?

Nếu họ trở về None, bạn có thể làm:

def get_random_foo_or_bar(): 
    return get_random_foo() or get_random_bar() 
Các vấn đề liên quan