2008-11-01 37 views
317

Tôi đã tự hỏi về các phương pháp hay nhất để chỉ ra các kết hợp đối số không hợp lệ trong Python. Tôi đã đi qua một vài tình huống mà bạn có một chức năng như vậy:Tôi nên đưa ra ngoại lệ nào đối với các kết hợp đối số xấu/bất hợp pháp trong Python?

def import_to_orm(name, save=False, recurse=False): 
    """ 
    :param name: Name of some external entity to import. 
    :param save: Save the ORM object before returning. 
    :param recurse: Attempt to import associated objects as well. Because you 
     need the original object to have a key to relate to, save must be 
     `True` for recurse to be `True`. 
    :raise BadValueError: If `recurse and not save`. 
    :return: The ORM object. 
    """ 
    pass 

Các ít phiền toái duy nhất với điều này là mỗi gói có riêng của mình, thường là hơi khác nhau BadValueError. Tôi biết rằng trong Java có tồn tại java.lang.IllegalArgumentException - là nó cũng hiểu rằng tất cả mọi người sẽ được tạo riêng của họ BadValueError s trong Python hoặc là có một phương pháp ưa thích?

Trả lời

348

Tôi chỉ sẽ tăng ValueError, trừ khi bạn cần một ngoại lệ cụ thể hơn ..

def import_to_orm(name, save=False, recurse=False): 
    if recurse and not save: 
     raise ValueError("save must be True if recurse is True") 

Có thực sự không có điểm trong việc class BadValueError(ValueError):pass - lớp tùy chỉnh của bạn là giống hệt nhau trong sử dụng đến ValueError, vậy tại sao không sử dụng?

+0

Đồng ý - Tôi hầu như luôn luôn sử dụng ValueError cho các công cụ như thế này, quá. – mipadi

+39

> "vậy tại sao không sử dụng?" - Tính đặc hiệu. Có lẽ tôi muốn nắm bắt một số lớp ngoài "MyValueError", nhưng không phải bất kỳ/tất cả "ValueError". –

+6

Vâng, do đó, một phần của câu hỏi cụ thể là nơi ValueError khác được nâng lên. Nếu hàm callee thích đối số của bạn nhưng gọi math.sqrt (-1) trong nội bộ, một người gọi có thể đang bắt ValueError mong rằng * các đối số * của nó không phù hợp. Có lẽ bạn chỉ cần kiểm tra tin nhắn trong trường hợp này ... – cdleary

8

Tôi hầu như chỉ nhìn thấy hình ảnh dựng sẵn ValueError được sử dụng trong trường hợp này.

65

tôi sẽ kế thừa từ ValueError

class IllegalArgumentError(ValueError): 
    pass 

Đó là đôi khi tốt hơn để tạo ra ngoại lệ của riêng mình, nhưng kế thừa từ một built-in một, mà là càng gần với những gì bạn muốn càng tốt.

Nếu bạn cần phát hiện lỗi cụ thể đó, bạn nên có tên.

+13

Ngừng viết các lớp học và ngoại lệ tùy chỉnh - http://pyvideo.org/video/880/stop-writing-classes –

+21

@HamishGrubijan video đó thật khủng khiếp. Khi bất cứ ai đề nghị sử dụng tốt một lớp, anh ta chỉ nói "Đừng dùng lớp." Rực rỡ. Các lớp học tốt. [Nhưng đừng dùng từ ngữ của tôi cho nó] (http://lucumr.pocoo.org/2013/2/13/moar-classes/). –

+5

@RobertGrant Không, bạn không hiểu. Video đó không thực sự về nghĩa đen "không sử dụng lớp học". Đó là về những thứ không quá phức tạp. – RayLuo

2

Tôi không chắc chắn Tôi đồng ý với thừa kế từ ValueError - giải thích của tôi về các tài liệu là ValueErrorchỉ nghĩa vụ phải được nêu ra bởi lệnh nội trú ... kế thừa từ nó hay nâng cao điều đó cho mình dường như không chính xác.

Lớn lên khi một built-in hoạt động hoặc chức năng nhận được một cuộc tranh cãi rằng có đúng loại nhưng một giá trị không phù hợp, và tình trạng này không phải là mô tả bởi một ngoại lệ chính xác hơn như IndexError.

- ValueError documentation

+4

Hoạt động tích hợp * HOẶC * chức năng .. – dbr

+0

So sánh http://www.google.com/codesearch?q=lang:python+class\+\w*Error\(([^E]\w*|E [^ x] \ w *) \): với http: //www.google.com/codesearch? q = lang: python + class \ + \ w * Lỗi \ (Ngoại lệ \): –

+0

@dbr: Vâng, tôi nghĩ rằng chúng có nghĩa là "(được xây dựng trong hoạt động hoặc chức năng)", không phải "(được xây dựng trong hoạt động) hoặc chức năng". Tôi sẽ nghĩ rằng họ đã tương phản với nó bằng cách nói "người dùng xác định" trong trường hợp thứ hai. – cdleary

0

Đồng ý với đề xuất của Markus để cuộn ngoại lệ của riêng bạn, nhưng văn bản của ngoại lệ phải làm rõ rằng vấn đề nằm trong danh sách đối số, chứ không phải các giá trị đối số riêng lẻ. Tôi muốn đề xuất:

class BadCallError(ValueError): 
    pass 

Được sử dụng khi đối số từ khóa bị thiếu bắt buộc cho cuộc gọi cụ thể hoặc giá trị đối số riêng lẻ hợp lệ nhưng không phù hợp với nhau. ValueError sẽ vẫn đúng khi một đối số cụ thể đúng loại nhưng nằm ngoài phạm vi.

Đây có phải là ngoại lệ chuẩn trong Python không?

Nói chung, tôi muốn kiểu Python trở nên sắc nét hơn một chút trong việc phân biệt các đầu vào xấu với hàm (lỗi của người gọi) từ kết quả không đúng trong hàm (lỗi của tôi). Vì vậy, cũng có thể có một BadArgumentError để phân biệt các lỗi giá trị trong các đối số từ các lỗi giá trị ở người dân địa phương.

Các vấn đề liên quan