by martinvol on 11/17/13, 6:26 PM with 41 comments
by mickeyp on 11/17/13, 8:22 PM
Bad:
assert InitialiseStuff() != False, 'Initialise failed'
If the optimising compiler is set to eliminiate assertions the InitialiseStuff function won't get called! This will (subtly, or not so subtly) break your program!
by mrmaddog on 11/18/13, 5:35 AM
assert x > 0, "x is not zero or negative"
When this fails, you're going to be at a loss to understand what actually happened. If you change the message to something like the following, you're going to have a much easier time tracing through your program to understand why your constraint was violated: assert x > 0, "Expected positive x, got: %d" % x
Once you get in the habbit of this, you'll quickly run up against style-guide imposed line limits. My usual trick here is to use parenthesis and let python's automatic string concatenation work its wonders, but you have to be careful because assert (x > 0, "This is my longer message "
"for x")
evaluates to a tuple, and thus is always true. Instead only use parens around the message: assert x > 0, ("This is my longer message "
"for x")
Lastly, don't use asserts in tests. Use the standard unittest library which will do a much better job explaining what was received, what was expected, and what the difference between them is.by ggchappell on 11/18/13, 1:47 AM
Here is (IMHO) the point: assert is for checking invariants.
That said, I doubt that a post like this is a good place to teach people what invariants are. Those who don't know should go learn. To some small extent, that might include the author, as, for example, pre- and post-conditions are not some special contract-thing that is separate from invariants; they are special kinds of invariants. (So, yes, use assert to check contracts; that's part of checking invariants)
And:
> You wouldn't write code like this:
if not isinstance(x, int):
raise AssertionError("not an int")
Sure I would, if x being an instance of int is an invariant of my code. But if it isn't, then I wouldn't.I also accept that, as the author says, "assert" has its quick-and-dirty uses. Putting an "assert False" around an unwritten portion of code is a reasonable thing to do, particularly if it is code that one expects to be used often, as the "assert" will continually complain of its own existence as long as it is there.
by shin_lao on 11/17/13, 8:55 PM
Carefully using assertions is a great way to see if you are building your code wrong. Like a way to tell you "you're trying to fit the wrong lego piece in".
by ak217 on 11/18/13, 5:14 AM
https://github.com/kislyuk/ensure
It's inspired by ensure.js, and defines a large (and growing) number of helpers to make assertions concise, easy to read, customizable, and more usable than the assert statement. (Feedback welcome!)
by ForHackernews on 11/17/13, 7:24 PM
by deckiedan on 11/18/13, 7:35 AM
class Username(unicode): pass
class Directory(unicode): pass
def updateUserHomeDir(name, dirname):
assert isinstance(name, Username)
assert isinstance(dirname, Directory)
update_etc_passwd(name=name, dirname=dirname)
or whatever. This only really starts to become useful when you start adding sanity checks into the classes: class Directory(unicode):
def __init__(*vargs, **kwargs):
super(Directory, self).__init__(*vargs, **kwargs)
if not os.path.is_dir(self):
if not os.path.exists(self):
make_dirs(self)
just a bit cleverer in reality. You then move all the directory-path sanity checks into there. You can also subclass further for `class ValidHomeDir(Directory)`, etc.The benefit of this is that you don't have to run your sanity checks more than once, you can pass the values around as much as you need and be sure that they have been initiated correctly. Use of your functions becomes at worst:
updateUserHomeDir(Username('dan'), Directory('/home/daniel'))
which isn't so bad, really.And it's fine to be optimised out, as the code paths are what are being checked here, not the user data. :-)
I don't know how "pythonic" the idea is, but it does seem reasonably elegant to me, and solves some of the problems of python's otherwise fun duck-typing.
by euphemize on 11/17/13, 8:26 PM
by penguindev on 11/17/13, 8:49 PM
Then they need to make something better for me. My c and python code isn't functional with asserts compiled out, because assert just makes my life easier.
In a perfect world, current assert semantics would be _DEBUG_ASSERT (all caps to let you know it has macro-ish behavior), and the normal assert would always be on.
by gcb1 on 11/17/13, 10:01 PM
by CraigJPerry on 11/17/13, 8:05 PM
by jheriko on 11/17/13, 8:14 PM
this comment is also scary from the C family of languages background:
"When using assert properly, this is a feature, but when assert is used inappropriately, it leads to code that is completely broken when running with the -O flag."
why don't people test their software by merely running it? esp in the config it will ship in.
by IgorPartola on 11/18/13, 1:33 AM
Proper design by contract support would be great too.