2014-11-04 21 views
9

Mã của tôi:Confused về thử/trừ trường hợp ngoại lệ tùy chỉnh

class AError(Exception): 
    print 'error occur' 
for i in range(3): 
    try: 
     print '---oo' 
     raise AError 
    except AError: 
     print 'get AError' 
    else: 
     print 'going on' 
    finally: 
     print 'finally' 

Khi tôi chạy đoạn mã trên, đầu ra là thế này:

error occur 
---oo 
get AError 
finally 
---oo 
get AError 
finally 
---oo 
get AError 
finally 

Tôi nghĩ rằng chuỗi "error occur" nên xảy ra ba lần, như "---oo", nhưng nó chỉ xảy ra một lần; tại sao?

Trả lời

11

Để làm rõ Paul's answer, đây là một ví dụ đơn giản:

class Test(object): 

    print "Class being defined" 

    def __init__(self): 
     print "Instance being created" 


for _ in range(3): 
    t = Test() 

Kết quả từ này sẽ là:

Class being defined 
Instance being created 
Instance being created 
Instance being created 

Mã trong định nghĩa class nhưng bên ngoài một inition phương pháp def chạy chỉ một lần, khi lớp được xác định.

Nếu bạn muốn mã để chạy bất cứ khi nào một thể hiện được tạo ra, nó phải ở trong __init__phương pháp dụ (hoặc, thỉnh thoảng, các __new__lớp phương pháp). Tuy nhiên, lưu ý rằng nếu bạn xác định __init__ cho một lớp con, có lẽ bạn nên đảm bảo rằng nó cũng kêu gọi của lớp cha __init__:

class AError(Exception): 

    def __init__(self, *args, **kwargs): 
     Exception.__init__(self, *args, **kwargs) # call the superclass 
     print 'error occur' # print your message 

Điều này đảm bảo rằng lớp con hỗ trợ các đối số cho các lớp cha; trong trường hợp của Exception, bạn có thể, ví dụ: vượt qua một thông báo lỗi:

>>> raise AError("Something went wrong.") 
error occur # your message gets printed when the instance is created 

Traceback (most recent call last): 
    File "<pyshell#11>", line 1, in <module> 
    raise AError("Something went wrong.") 
AError: Something went wrong. # the error message passes through to the traceback 

Để giải thích về cú pháp *args, **kwargs, nếu bạn không quen thuộc với nó, xem ví dụ What does ** (double star) and * (star) do for parameters?. Bạn cũng có thể sử dụng super để gọi các phương thức siêu lớp, xem ví dụ: Understanding Python super() with __init__() methods.

+0

Câu trả lời này rất rõ ràng, tôi hiểu rồi. 3Q rất nhiều, vì vậy kand của bạn! –

5

'error occur' chỉ được in một lần, cho cả lớp.

Bạn có thể mong đợi nó sẽ chạy cho mỗi phiên bản của lớp đã được tạo.

Đối với điều đó xảy ra, đặt nó trong __init__ chức năng,

class AError(Exception): 
    def __init__(self): 
     print 'error occur' 

__init__ được gọi khi một thể hiện của AError được tạo ra.

+3

Bạn nên đề cập đến sự khác nhau giữa định nghĩa lớp và tạo Ví dụ, tức là * tại sao * điều này tạo nên sự khác biệt. Ngoài ra, '__init__' nên lấy đối số và gọi trình khởi tạo siêu lớp, nếu không, lỗi tùy chỉnh sẽ không hỗ trợ ví dụ: một thông báo lỗi. – jonrsharpe

+0

Tôi đã quên sự khác biệt giữa phương pháp lớp và phương pháp thể hiện, 3Q để chỉ đường. –

1

Chuỗi 'error occur' chỉ xuất hiện một vì Python thực thi nó khi phân tích định nghĩa lớp học AError của bạn.

Nếu bạn muốn nhận được nó thực hiện mỗi khi bạn tạo một thể hiện của lớp học của bạn, bạn phải xác định initialiser của lớp:

class AError(Exception): 
    def __init__(self): 
     print 'error occur' 

for i in range(3): 
    try: 
     print '---oo' 
     raise AError 
    except AError: 
     print 'get AError' 
    else: 
     print 'going on' 
    finally: 
     print 'finally' 

Hãy vui vẻ (và đọc hướng dẫn ngôn ngữ có lẽ ...)

+0

Xem câu trả lời của tôi (và bình luận của tôi về Paul's) - 'AError .__ init__' nên gọi 'Ngoại lệ .__ init__' và xử lý các đối số thích hợp. – jonrsharpe

2

Tôi khuyên bạn không nên đặt bất kỳ câu lệnh in nào trong Ngoại lệ, đặc biệt là.không phải nhà thầu của họ! Các ngoại lệ là các thực thể ngữ nghĩa và bạn có thể in chúng ra nếu bạn cần. Nếu bạn phải tự động in ít nhất hãy sử dụng logging hoặc gói tương tự.

Những gì bạn có thể không nhận thức được là bạn có thể thu thập các trường hợp ngoại lệ cho việc sử dụng trong mệnh đề except như vậy:

class MyError(Exception): 
    pass 

for i in range(3): 
    try: 
     print '---oo' 
     raise MyError("error msg no. {}".format(i)) 
     # Exception usually always accept a string as their first parameter 
    except MyError, ex: 
     # Exception instance available inside the except clause as `ex` 
     print ex 
    else: 
     print 'going on' 
    finally: 
     print 'finally' 
Các vấn đề liên quan