On 16Jul2019 23:49, Alan Gauld <alan.ga...@yahoo.co.uk> wrote:
On 16/07/2019 22:56, Mats Wichmann wrote:
thrown. This gets watered down to the mantra "Don't throw
exceptions from
within constructors." Does this carry over to Python?
If you mean __init__, that's not a constructor, so you should set your
mind at rest :) It's more properly an "initializer", the instance has
already been constructed when it's called.
FWIW The true constructor is __new__() and its quite rarely overridden
by application programmers. But if you do, it's not common that you'd do
anything that would merit an exception. __new__ pretty much just sets
up the structure of the object ready for initialisation by __init__.
Incidentally, this two stage construction/initialisation is also found
in other OOP languages like Smalltalk and Objective C (and Lisp?).
And to return to the OP's question:
The __init__ method (and arguably __new__ if you touch it - very rare)
is like other Python code: resource allocation should normally get
unwound as objects become unreferenced. So raising an exception should
be a pretty safe thing to do.
That is a simplification. Of course if you implement an object with side
effects _outside_ the Python object space (maybe it opened a scratch
file to support something), it is your responsibility to ensure release
in the object's __del__ method. But an object that just allocates a
bunch of lists or dicts or the like? Python will clean that up for you.
That said, I try to do cheap initialisation before exspensive
initialisation. So allocating locks, opening files, starting worker
threads: these come at the bottom of the __init__ method.
Also, it is _ROUTINE_ to raise exceptions from __init__: like any other
method we _expect_ you to raise ValueError if the initialiser parameters
are insane (negatively sized arrays, etc etc).
So in Python, raising exceptions in __init__ is normal: it shouldn't
happen when you programme is running correctly of course, but it is the
_preferred_ action when your initialiser cannot complete correctly.
Consider:
x = Foo(....)
After this assignment we expect "x" to be a usable instance of Foo. We
don't put special checks; what would such checks look like? (There are
some answers for that, but they're all poor.)
So raising an exception is what happens if __init__ fails.
Cheers,
Cameron Simpson <c...@cskk.id.au>
_______________________________________________
Tutor maillist - Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor