2013-06-27 31 views
7

Trước hết, tôi biết rằng hàm __init__() của một lớp trong Python không thể trả về một giá trị, vì vậy đáng buồn là tùy chọn này không khả dụng.Python __init__ trả lại lỗi để tạo

Do cấu trúc mã của tôi, nên có xác nhận dữ liệu (và lời nhắc để người dùng cung cấp thông tin) bên trong hàm __init__ của lớp. Tuy nhiên, điều này có nghĩa rằng việc tạo ra các đối tượng có thể thất bại, và tôi muốn có thể phục hồi một cách duyên dáng từ này.

Tôi đã tự hỏi cách tốt nhất để tiếp tục điều này là gì. Tôi đã xem xét việc thiết lập một boolean toàn cầu như một lá cờ 'xây dựng hợp lệ', nhưng tôi không muốn.

Bất kỳ ý tưởng nào khác (ngoài việc tái cấu trúc để các xác nhận có thể xảy ra bên ngoài việc khởi tạo và các giá trị được chuyển thành đối số)? Tôi về cơ bản đang tìm kiếm một cách để có được 0 trở về thành công và trả về -1 trên thất bại trong quá trình khởi tạo. (Giống như hầu hết các cuộc gọi hệ thống C)

+8

Tăng ngoại lệ. –

+1

Trả về 0 thành công và -1 về thất bại là rất un-Pythonic. Lỗi trả về là xấu, vì chúng dễ bỏ qua và tiết kiệm để xử lý. Ngày đầu đó, sử dụng 0 và -1 là giá trị boolean chỉ thêm nhầm lẫn mà không có lợi ích. Không đúng khi sử dụng Python để viết mã C. – abarnert

+0

Khi @jsbueno chỉ ra câu trả lời của mình, các cá thể lớp là _initialized_ trong '__init __()', không được tạo ra, đó là lý do tại sao nó không 'trả về' một giá trị. Thay vì sử dụng biến toàn cầu để phát hiện lỗi hoặc thực hiện một ngoại lệ, bạn có thể thêm thành viên dữ liệu vào lớp của bạn để biểu thị trạng thái của nó và sau đó kiểm tra trực tiếp giá trị của nó hoặc gọi phương thức trả về giá trị của nó sau '__init __()' được gọi để xác định xem có bất cứ điều gì (và có thể là gì) khi sai. – martineau

Trả lời

11

Bạn có thể nâng cao một ngoại lệ khi một trong hai assertio thất bại, hoặc - nếu bạn thực sự không muốn hoặc không thể làm việc với trường hợp ngoại lệ, bạn có thể viết phương pháp __new__ trong lớp học của bạn - bằng Python, __init__ là về mặt kỹ thuật một Phương thức "initializer" - và nó sẽ điền vào các thuộc tính và thu được một số tài nguyên và các đối tượng khác mà bạn cần trong vòng đời của nó - Tuy nhiên, Python định nghĩa một hàm tạo thực, phương thức __new__, được gọi trước __init__ - và không giống như vậy, __new__ thực sự trả về một giá trị: bản thân mới được tạo (uninitialized).

Vì vậy, bạn có thể đặt séc bên trong __new__ và đơn giản trả về Không có gì là không thành công - ngược lại, trả về kết quả cuộc gọi đến phương thức siêu lớp __new__ (người ta không thể phân bổ bộ nhớ thực cho đối tượng bằng Python thuần túy) , vì vậy cuối cùng bạn phải gọi một constructor viết bằng mã nguồn gốc trong một lớp cha - thường đây là object.__new__ trong cơ sở của hệ thống cấp bậc lớp học của bạn

NB:. trong Python 2, bạn phải có object là lớp cơ sở cho hệ thống phân cấp của bạn - nếu không, không chỉ gọi là __new__, vì toàn bộ nhiều tính năng được thêm vào sau này đối với các đối tượng Python sẽ không hoạt động. class MyClass(object):, không bao giờ class MyClass: - trừ khi bạn đang sử dụng Python3.

+0

Bạn nói '__new__' được gọi trước' __init__'. Tôi chỉ thử điều này, nhưng '__new__' KHÔNG được gọi khi tôi tạo một thể hiện của một lớp (Py2.7). –

+0

Tôi đã tìm thấy nó. Bạn cần phải mở rộng đối tượng trong lớp của bạn. Nếu không có điều đó, mới sẽ không được gọi! –

+0

No. Nếu tôi bỏ qua lớp cơ sở đối tượng, '__new__' không được gọi tự động. Đi con số! –

0

Bạn đã cân nhắc việc tăng một ngoại lệ? Đó là cách thông thường để báo hiệu lỗi.

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