2014-11-04 8 views
9

Mój kod:zna spróbuj/z wyjątkiem niestandardowego Exception

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' 

Kiedy uruchomić powyższy kod, wyjście to:

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

myślę ciąg "error occur" powinno nastąpić trzy razy, jak "---oo", ale występuje tylko raz; czemu?

Odpowiedz

11

Aby wyjaśnić Paul's answer, oto prosty przykład:

class Test(object): 

    print "Class being defined" 

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


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

Wyjście z tego będzie:

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

Kod w definicji class ale poza metoda def ganization biegnie tylko raz, kiedy klasa jest zdefiniowana.

Jeśli chcesz kod do uruchomienia gdy instancja jest tworzona, powinien on być w __init__instancji metody (lub Czasami __new__klasa metoda). Należy jednak pamiętać, że jeśli zdefiniować __init__ dla podklasy, powinieneś upewnić się, że wywołuje także nadklasą na __init__:

class AError(Exception): 

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

Gwarantuje to, że podklasa obsługuje argumenty dla nadrzędnej; w przypadku Exception można np. przekazać komunikat o błędzie:

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

Wyjaśnienie składni *args, **kwargs, jeśli nie są zaznajomieni z tym, patrz na przykład What does ** (double star) and * (star) do for parameters?. Możesz także użyć super, aby wywołać metody nadklasy, zobacz np. Understanding Python super() with __init__() methods.

+0

Ta odpowiedź jest bardzo jasna, rozumiem. 3Q bardzo, więc kand z was! –

5

'error occur' zostaje wydrukowany tylko raz, dla całej klasy.

Prawdopodobnie spodziewałeś się, że zostanie uruchomiony dla każdej instancji klasy, która została utworzona.

Aby tak się stało, umieścić go w funkcji __init__,

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

__init__ jest wywoływana, gdy instancja AError jest tworzony.

+3

Należy wspomnieć różnicę między definicji klasy i tworzenia instancji, tj * dlaczego * to robi różnicę. Dodatkowo, '__init__' powinno przyjmować argumenty i wywoływać inicjalizator klasy nadklasy, w przeciwnym razie błąd niestandardowy nie będzie obsługiwał np. komunikat o błędzie. – jonrsharpe

+0

Zapomniałem o różnicy między metodą klasową a metodą instancji, 3Q za podanie wskazówek. –

1

Ciąg znaków pojawia się tylko jeden, ponieważ Python wykonuje go podczas analizy definicji klasy AError.

Jeśli chcesz dostać to wykonywane za każdym razem utworzyć instancję klasy, należy zdefiniować klasę za initialiser:

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' 

Miłej zabawy (a może przeczytać instrukcję języka ...)

+0

Zobacz moją odpowiedź (i mój komentarz na temat Paula) - "AError .__ init__" powinien wywołać 'Exception .__ init__' i obsłużyć odpowiednie argumenty. – jonrsharpe

2

Zaleca się, aby nie umieszczać żadnych instrukcji drukowania w swoim wyjątku, zwł.nie ich konstruktorzy! Wyjątki są semantycznymi bytami i możesz je wydrukować, jeśli potrzebujesz. Jeśli musisz zautomatyzować drukowanie, użyj przynajmniej wersji logging lub podobnego pakietu.

Co może nie być świadomy, że można zbierać wystąpienie wyjątku do użytku w klauzuli except tak:

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'