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

Reply via email to