Re: When to use assert
Chris Angelico wrote: On Fri, Oct 24, 2014 at 6:49 PM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: addresses = [get_address(name) for name in database] assert all(address for address in addresses) # ... much later on ... for i, address in enumerate(addresses): if some_condition(): addresses[i] = modify(address) assert addresses[i] will either identify the culprit, or at least prove that neither get_address() nor modify() are to blame. Because you're using an assertion, it's easy to leave the asserts in place forever, and disable them by passing -O to the Python interpreter in production. The first assertion is fine, assuming that the emptiness of your address corresponds to falsiness as defined in Python. (This could be safe to assume, if the address is an object that knows how to boolify itself.) The second assertion then proves that modify() isn't returning nothing, but that might be better done by sticking the assertion into modify itself. Sure. If you can modify the function, getting it to check it's own post-condition is a good strategy. But you might not be able to do that. Perhaps you don't have the source code, or its from a third-party library and you don't want to have to keep hacking your copy every time it's updated, or you're calling an external library written in Java. (And yes, there are work-arounds for those scenarios too. Aren't choices wonderful?) And that's what I'm talking about: checking a function's postcondition with an assert implies putting that assertion after every call, There's no rule that you have to use an assertion after *every* call to a function. If you can check the post-condition inside the function, that's great. If you can't, then use your judgement. More asserts are not necessarily better, just as more unit tests are not necessarily better. You have to make a value judgement based on how much you trust the code, trust your own skills, trust your colleagues who will be maintaining the code in your absence, versus the maximum density of asserts per line of other code. and anything that you have to do every time you call a function belongs inside that function. Imagine writing this kind of defensive code, and then having lots of places that call modify()... and missing the assert in some of them. Can you trust what you're getting back? Well, if the function is perfect, then adding more assertions won't uncover bugs that aren't there. And if the function is buggy, then adding more assertions will increase the likelihood that you'll discover those bugs earlier rather than later. How much do you trust the function? One test is better than no tests at all, but a thousand tests is not necessarily better than ten. The same applies to assertions. One might say that assertions can be considered tests that automatically run every time you run your code (in debugging mode), rather than needing to remember to run a special test program. In the absence of correctness proofs for your code, anything you do (unit tests, assertions, regression tests, etc.) is just a statistically sampling of all the potential paths your code might take, hoping to capture bugs. As any statistician will tell you, eventually you will reach the point of diminishing returns, where adding more samples isn't worth the cost. That point will depend on the cost in programmer effort, the performance implications, and your confidence in the code. [Aside: it would be nice if Python did it the other way around, and [require a --debugging switch to turn assertions on. Oh well.] Maybe. But unless someone actually tests that their assertions are being run, there's the risk that they're flying blind and assuming that it's all happening. There'll be all these lovely checked comments... or so people think. Nobody ever runs the app with --debugging, so nobody ever sees anything. Absolutely. And if you write unit tests but never actually run them, the same thing applies. You need a process that actually runs the code in debugging mode, and/or runs the tests. Or if the unit tests all pass but don't actually do anything useful? def test_critical_code_path(self): # Make sure application works correctly. self.assertTrue(True) Do I have to link to the DailyWTF showing that some people actually do write tests like this? Sure, why not :-) http://thedailywtf.com/articles/Productive-Testing Bad programmers can screw up anything. Assertions and test suites are complementary, not in opposition, like belt and braces. Assertions insure that the code branch will be tested if it is ever exercised, something test suites can't in general promise. Here's a toy example: def some_function(value): import random random.seed(value) if random.random() == 0.25000375: assert some_condition else: pass Try writing a unit test that guarantees to test the some_condition branch :-)
Re: When to use assert
On Sun, Oct 26, 2014 at 8:39 PM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: In the absence of correctness proofs for your code, anything you do (unit tests, assertions, regression tests, etc.) is just a statistically sampling of all the potential paths your code might take, hoping to capture bugs. As any statistician will tell you, eventually you will reach the point of diminishing returns, where adding more samples isn't worth the cost. That point will depend on the cost in programmer effort, the performance implications, and your confidence in the code. That's about the size of it, I guess. How much testing versus how much time actually spent coding? I'm pretty sure a lot of my code has the wrong ratio... I'm just not sure, for a lot of the code, which direction it's wrong :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
Dan Stromberg wrote: I like to use assertions and if cond: raise ValueError('foo') a lot. I think Eiffel may be the poster-child for a language with pre-conditions, post-conditions and assertions. Yes. I don't think Eiffel is the only language with explicit support for testing invariants, but it's probably the best known one. https://archive.eiffel.com/doc/online/eiffel50/intro/language/invitation-07.html Others include Ada2012, Mercury, D, Perl6, Cobra, Clojure, and others. Cobra is especially interesting as the syntax is heavily influenced by Python's. http://cobra-language.com/trac/cobra/wiki/Contracts I think you're in good company - a lot of developers don't use assertions much. You in this context is Chris Angelico. I like assertions, because they tend to stop bugs pretty quickly. If you have 3 functions, one calling another calling another, assertions in each can keep you from having to backtrack among them when debugging, instead going directly to the problem's source. Yes, the purpose of assertions is to help errors be discovered as close to the cause as possible, rather than somewhere much later on. Consider: addresses = [get_address(name) for name in database] # ... much later on ... for i, address in enumerate(addresses): if some_condition(): addresses[i] = modify(address) # ... much later on ... for address in list_of_addresses: process_non_empty_address(address) where you can't easily modify or check the get_address() and modify() functions. If you have a failure in process_non_empty_address, due to a violation of the address must not be empty invariant, which function is to blame? You could wrap them and find out that way: from somewhere import get_address as _get_addr def get_address(*args, **kwargs): result = _get_addr(*args, **kwargs) if not result: raise RuntimeError(bug in get_address) return result and under some circumstances that's a good strategy, but often you just want to determine which function is violating the constraint, fix that one, and leave the other unmodified. addresses = [get_address(name) for name in database] assert all(address for address in addresses) # ... much later on ... for i, address in enumerate(addresses): if some_condition(): addresses[i] = modify(address) assert addresses[i] will either identify the culprit, or at least prove that neither get_address() nor modify() are to blame. Because you're using an assertion, it's easy to leave the asserts in place forever, and disable them by passing -O to the Python interpreter in production. [Aside: it would be nice if Python did it the other way around, and require a --debugging switch to turn assertions on. Oh well.] This is the job of a test suite. Test suites are great, and I can't really question your reliance on them. I love having lots of automated tests. But for the reason I described above, I still like having lots of assertions. Assertions and test suites are complementary, not in opposition, like belt and braces. Assertions insure that the code branch will be tested if it is ever exercised, something test suites can't in general promise. Here's a toy example: def some_function(value): import random random.seed(value) if random.random() == 0.25000375: assert some_condition else: pass Try writing a unit test that guarantees to test the some_condition branch :-) [Actually, it's not that hard, if you're willing to monkey-patch the random module. But you may have reasons for wanting to avoid such drastic measures.] I don't know what value will cause some_function() to take the some_condition branch, but I know that if it ever takes that branch, the assert will guard it, regardless of whether or not I've written a unit test to cover that situation. You don't pepper your code with assertions to the effect that I just pushed something onto my queue, it should now have this item in it; you create a test case for it, and verify your function there. In the rest of the code, you trust that your test suite passes, and don't waste time with assertions. I wouldn't test that a value was added to a queue immediately after adding it. That's excessive, and may even require an abstraction violation. But if, for example, I have a string with 3 known-good values, I'll if/elif/elif/else, and make the else raise an AssertionError. The assertion should never fire, but if the code changes, it could, and if there's a typo somewhere, it could then too. I like this style: assert x in (a, b, c) if x == a: do_this() elif x == b: do_that() else: assert x == c do_something_else() Why do I prefer that? To defend against future code changes. Defensive programming can defend not only against bugs in the current code, but also bugs in *future* code. Consider this common case: # x is either a or b. if x == a: do_this() elif x == b: do_that() else: # x must
Re: When to use assert
On Fri, Oct 24, 2014 at 6:49 PM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: addresses = [get_address(name) for name in database] assert all(address for address in addresses) # ... much later on ... for i, address in enumerate(addresses): if some_condition(): addresses[i] = modify(address) assert addresses[i] will either identify the culprit, or at least prove that neither get_address() nor modify() are to blame. Because you're using an assertion, it's easy to leave the asserts in place forever, and disable them by passing -O to the Python interpreter in production. The first assertion is fine, assuming that the emptiness of your address corresponds to falsiness as defined in Python. (This could be safe to assume, if the address is an object that knows how to boolify itself.) The second assertion then proves that modify() isn't returning nothing, but that might be better done by sticking the assertion into modify itself. And that's what I'm talking about: checking a function's postcondition with an assert implies putting that assertion after every call, and anything that you have to do every time you call a function belongs inside that function. Imagine writing this kind of defensive code, and then having lots of places that call modify()... and missing the assert in some of them. Can you trust what you're getting back? [Aside: it would be nice if Python did it the other way around, and require a --debugging switch to turn assertions on. Oh well.] Maybe. But unless someone actually tests that their assertions are being run, there's the risk that they're flying blind and assuming that it's all happening. There'll be all these lovely checked comments... or so people think. Nobody ever runs the app with --debugging, so nobody ever sees anything. Assertions and test suites are complementary, not in opposition, like belt and braces. Assertions insure that the code branch will be tested if it is ever exercised, something test suites can't in general promise. Here's a toy example: def some_function(value): import random random.seed(value) if random.random() == 0.25000375: assert some_condition else: pass Try writing a unit test that guarantees to test the some_condition branch :-) [Actually, it's not that hard, if you're willing to monkey-patch the random module. But you may have reasons for wanting to avoid such drastic measures.] Easy. You craft a test case that passes the right argument, and then have the test case test itself. You will want to have a script that figures out what seed value to use: def find_seed(value): import random for seed in range(100): # Restrict to not-too-many tries random.seed(seed) if random.random() == value: return seed I didn't say it'd be efficient to run, but hey, it's easy. I've no idea how many bits of internal state the default Python RNGs use, but testing a million seeds took a notable amount of time, so I told it to fail after that many. (And I didn't find one that gave that result.) But actually, it would be really simple to monkey-patch. And in any non-toy situation, there's probably something more significant being tested here... unless you really are probing a random number generator or something, in which case you probably know more about its internals. I like this style: assert x in (a, b, c) if x == a: do_this() elif x == b: do_that() else: assert x == c do_something_else() If all your branches are simple function calls, I'd be happy with a KeyError instead of an AssertionError or RuntimeError. {a:do_this, b:do_that, c:do_something_else}[x]() I was talking to a student this week who had a long if/elif chain that translated keywords into values, something like this: def get_whatever_value(kwd): if kwd == 'value_should_be_50': return 50 elif kwd == 'value_wants_to_be_75': return 75 elif kwd == 'one_hundred': return 100 There was no 'else' clause, so in the event of an incorrect keyword, it would return None. Now, I could have advised adding an else ValueError or an assertion, but my preferred technique here is a simple dict lookup. Simpler AND guarantees that all inputs are checked. Or is that insufficiently paranoid? With good tests, you're probably fine. Is it possible to be too paranoid when it comes to tests? Yeah, it is. I said earlier about checking that len() returns an integer. The only way[1] for len(some_object) to return a non-integer is for someone to have shadowed len, and if you're asserting to see if someone's maliciously shadowing builtins, you *really* need a hobby. But hey. Maybe asserting *is* your hobby! ChrisA [1] Cue the response pointing out some way that it'll return something else. I wasn't able to break it, though. -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
Chris Angelico wrote: On Wed, Oct 22, 2014 at 12:44 PM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: def do_something(instance_or_id): instance = Model.get(instance_or_id) assert isinstance(instance, Model) # Code that assumes that instance is an object of type Model That means that the logic for what is acceptable as a Model is all in one place, namely the Model.get method, and callers don't need to care about the pre-condition argument is a Model or an integer ID, they only need to care about the post-condition result of get() is a Model. And at that point, the assertion is redundant, on par with: a = len(seq) assert isinstance(a, int) because you shouldn't have to assert what's part of a function's guarantee. That depends on how well you trust the function, how paranoid you are, and whether you wish to include a checked comment, among other considerations. I'd prefer to write the above than: a = len(seq) # At this point, a is an int. because comments inside code that aren't checked are technically known as lies http://import-that.dreamwidth.org/956.html. Ha ha only serious. I wouldn't write such a comment for len() since I would expect anyone reading the code to know what len() does, but the same doesn't necessarily apply for every function call I make. Checking the post-condition of a built-in like len() is too paranoid for my tastes, as len() enforces the rule that __len__() methods return a non-negative integer, and there are millions of lines of Python code around the world calling len(). Somebody surely have noticed by now if len() violated that post-condition. But for a function from my own code base, where I might only have dozens of users (oh to have that many!) and fewer unit tests than perhaps I ought to, I might not be quite so confident that the assertion was redundant. To err is human, and so there are occasions when it is appropriate to trust but verify. As I wrote: This is why assert can be divisive. Since we can vary in our confidence about the correctness of code, one person's useful assertion may be another person's useless runtime test. http://import-that.dreamwidth.org/676.html -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On Thu, Oct 23, 2014 at 2:49 AM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: Chris Angelico wrote: And at that point, the assertion is redundant, on par with: a = len(seq) assert isinstance(a, int) because you shouldn't have to assert what's part of a function's guarantee. That depends on how well you trust the function, how paranoid you are, and whether you wish to include a checked comment, among other considerations. I'd prefer to write the above than: a = len(seq) # At this point, a is an int. because comments inside code that aren't checked are technically known as lies http://import-that.dreamwidth.org/956.html. Ha ha only serious. ... Checking the post-condition of a built-in like len() is too paranoid for my tastes... As I wrote: This is why assert can be divisive. Since we can vary in our confidence about the correctness of code, one person's useful assertion may be another person's useless runtime test. I agree that the assert is preferable to the comment. But maybe my level of paranoia is just lower than most people's, as I wouldn't bother checking the post-conditions of pretty much anything. Do you put these assertions every time you call the function? Every time you're depending on its return value? At what point should you stop writing Python code and start using a language with a lot more boilerplate and checking (I believe Haskell fits that, though I'm not overly familiar with the language)? This is the job of a test suite. You don't pepper your code with assertions to the effect that I just pushed something onto my queue, it should now have this item in it; you create a test case for it, and verify your function there. In the rest of the code, you trust that your test suite passes, and don't waste time with assertions. Or is that insufficiently paranoid? ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On Wed, Oct 22, 2014 at 9:01 AM, Chris Angelico ros...@gmail.com wrote: On Thu, Oct 23, 2014 at 2:49 AM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: Chris Angelico wrote: I agree that the assert is preferable to the comment. But maybe my level of paranoia is just lower than most people's, as I wouldn't bother checking the post-conditions of pretty much anything. Do you put these assertions every time you call the function? Every time you're depending on its return value? At what point should you stop writing Python code and start using a language with a lot more boilerplate and checking (I believe Haskell fits that, though I'm not overly familiar with the language)? I like to use assertions and if cond: raise ValueError('foo') a lot. I think Eiffel may be the poster-child for a language with pre-conditions, post-conditions and assertions. I think you're in good company - a lot of developers don't use assertions much. I like assertions, because they tend to stop bugs pretty quickly. If you have 3 functions, one calling another calling another, assertions in each can keep you from having to backtrack among them when debugging, instead going directly to the problem's source. This is the job of a test suite. Test suites are great, and I can't really question your reliance on them. I love having lots of automated tests. But for the reason I described above, I still like having lots of assertions. You don't pepper your code with assertions to the effect that I just pushed something onto my queue, it should now have this item in it; you create a test case for it, and verify your function there. In the rest of the code, you trust that your test suite passes, and don't waste time with assertions. I wouldn't test that a value was added to a queue immediately after adding it. That's excessive, and may even require an abstraction violation. But if, for example, I have a string with 3 known-good values, I'll if/elif/elif/else, and make the else raise an AssertionError. The assertion should never fire, but if the code changes, it could, and if there's a typo somewhere, it could then too. Or is that insufficiently paranoid? With good tests, you're probably fine. -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On Saturday, November 16, 2013 11:35:50 PM UTC-8, Steven D'Aprano wrote: The question of when to use the assert statement comes up occasionally, usually in response to somebody misusing it, so I thought I'd write a post describing when and why to use assertions, and when not to. For those who aren't aware of it, Python's assert checks a condition, if it is true it does nothing, and if it is false it raises an AssertionError with an optional error message. For example: py x = 23 py assert x 0, x is not zero or negative py assert x%2 == 0, x is not an even number Traceback (most recent call last): File stdin, line 1, in module AssertionError: x is not an even number Many people use asserts as a quick and easy way to raise an exception if an argument is given the wrong value. But this is wrong, dangerously wrong, for two reasons. The first is that AssertionError is usually the wrong error to give when testing function arguments. You wouldn't write code like this: if not isinstance(x, int): raise AssertionError(not an int) you'd raise TypeError instead. assert raises the wrong sort of exception. But, and more dangerously, there's a twist with assert: it can be compiled away and never executed, if you run Python with the -O or -OO optimization flags, and consequently there is no guarantee that assert statements will actually be run. 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. When should use assert? In no particular order, assertions should be used for: * defensive programming; * runtime checks on program logic; * checking contracts (e.g. pre-conditions and post-conditions); * program invariants; and * checked documentation. (It's also acceptable to use assert when testing code, as a sort of quick- and-dirty poor man's unit testing, so long as you accept that the tests simply won't do anything if you run with the -O flag. And I sometimes use assert False in code to mark code branches that haven't been written yet, and I want them to fail. Although raise NotImplementedError is probably better for that, if a little more verbose.) Opinions on assertions vary, because they can be a statement of confidence about the correctness of the code. If you're certain that the code is correct, then assertions are pointless, since they will never fail and you can safely remove them. If you're certain the checks can fail (e.g. when testing input data provided by the user), then you dare not use assert since it may be compiled away and then your checks will be skipped. It's the situations in between those two that are interesting, times when you're certain the code is correct but not *quite* absolutely certain. Perhaps you've missed some odd corner case (we're all only human). In this case an extra runtime check helps reassure you that any errors will be caught as early as possible rather than in distant parts of the code. (This is why assert can be divisive. Since we vary in our confidence about the correctness of code, one person's useful assert is another person's useless runtime test.) Another good use for asserts is checking program invariants. An invariant is some condition which you can rely on to be true unless a bug causes it to become false. If there's a bug, better to find out as early as possible, so we make a test for it, but we don't want to slow the code down with such tests. Hence assert, which can be turned on in development and off in production. An example of an invariant might be, if your function expects a database connection to be open when it starts, and promises that it will still be open when it returns, that's an invariant of the function: def some_function(arg): assert not DB.closed() ... # code goes here assert not DB.closed() return result Assertions also make good checked comments. Instead of writing a comment: # when we reach here, we know that n 2 you can ensure it is checked at runtime by turning it into an assert: assert n 2 Assertions are also a form of defensive programming. You're not protecting against errors in the code as it is now, but protecting against changes which introduce errors later. Ideally, unit tests will pick those up, but let's face it, even when tests exist at all, they're often incomplete. Build-bots can be down and nobody notices for weeks, or people forget to run tests before committing code. Having an internal check is another line of defence against errors sneaking in, especially those which don't noisily fail but cause the code to malfunction and return
Re: When to use assert
Anton wrote: I use ORM and often need to write a function that either takes an id of the record or already loaded model object. So I end up writing a piece of code like below: def do_something(instance): if isinstance(instance_or_id, int): instance = Model.get(instance) assert isinstance(instance, Model) # Code that assumes that instance is an object of type Model do_somthing is not a part of public library, though it is a public function, which can and intended to be used by other programmers; and assert should never happen if a client uses the function as planned. I think you mean the assert should never fail. That seems like a reasonable use for assert, with a proviso below. It's behaving like a checked comment or a post-condition test: asserting that Model.get returns a Model instance. But, the idea of *requiring* Model.get to return a Model instance may be inadvisable. It goes against duck-typing, and it prevents Model from making some kinds of implementation changes that might break your post-condition that get() always returns an instance. For example, it might return a proxy object instead, and then your assert will fail. I wonder if this use-case is controversial to this part: Many people use asserts as a quick and easy way to raise an exception if an argument is given the wrong value. But this is wrong, dangerously wrong, for two reasons. The first is that AssertionError is usually the wrong error to give when testing function arguments. You wouldn't write code like this: if not isinstance(x, int): raise AssertionError(not an int) you'd raise TypeError instead. assert raises the wrong sort of exception. No, because the nature of the exception depends on the intent of the test and the audience who is expected to see it. In an ideal world, AssertionError should never be seen by the end user, or the developer calling your code (assuming that she obeys the documented requirements of your code). A failed assert should be considered an internal error, which the user never sees. Since the failure: Model.get has stopped returning Model instances is likely to be an internal problem (oops, I broke the get() method, better fix that) rather than an expected error, using assert is okay. What would *not* be okay is something like this: def do_something(instance_or_id): if isinstance(instance_or_id, int): instance = Model.get(instance_or_id) assert isinstance(instance, Model) # Code that assumes that instance is an object of type Model since that fails with (for example) do_something(None): either the assert is not checked at all, and there will be some mysterious failure deep inside your code, or the caller will see AssertionError instead of TypeError, violating user expectations and good design that type errors should raise TypeError. A better way to write this might be to have Model.get() responsible for the error checking, and then just delegate to it: class Model: def get(self, obj): if isinstance(obj, Model): return obj elif isinstance(obj, int): model = Model(do something here) return model raise TypeError('expected an int ID or a Model instance') def do_something(instance_or_id): instance = Model.get(instance_or_id) assert isinstance(instance, Model) # Code that assumes that instance is an object of type Model That means that the logic for what is acceptable as a Model is all in one place, namely the Model.get method, and callers don't need to care about the pre-condition argument is a Model or an integer ID, they only need to care about the post-condition result of get() is a Model. -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On Wed, Oct 22, 2014 at 12:44 PM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: def do_something(instance_or_id): instance = Model.get(instance_or_id) assert isinstance(instance, Model) # Code that assumes that instance is an object of type Model That means that the logic for what is acceptable as a Model is all in one place, namely the Model.get method, and callers don't need to care about the pre-condition argument is a Model or an integer ID, they only need to care about the post-condition result of get() is a Model. And at that point, the assertion is redundant, on par with: a = len(seq) assert isinstance(a, int) because you shouldn't have to assert what's part of a function's guarantee. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On 17/11/13 13:33, Roy Smith wrote: Every once in a while, I'll get into a situation where something is happening that I just can't understand. If a given pice of code is being called, there's NO WAY the program should be exhibiting the behavior it's exhibiting. But, there's also NO WAY that piece of code can't be getting called. So, I stick assert 0 in the code an re-run the program to see if I get an AssertionError. If I do, then I know the code is being run. If I don't then I know it's not. Either way, I know more about what's going on than I did before. Once I know what's going on, I remove the assert. Are assertions the right thing in that case? I'm becoming more and more inclined to the idea that if you want to know whether code is getting run, you should put a debug log in, and leave it in. That way it's easier to track down the next bug (I don't know about others, but when I write buggy code I go all-out and put lots of bugs in rather than just one). Rob -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On 17 November 2013 13:33, Roy Smith r...@panix.com wrote: So, I stick assert 0 in the code an re-run the program to see if I get an AssertionError. If I do, then I know the code is being run. If I don't then I know it's not. Either way, I know more about what's going on than I did before. Once I know what's going on, I remove the assert. If the program is invoked from a terminal I would probably go with 'import pdb; pdb.set_trace()' rather than 'assert 0'. Then you can check much more than whether or not the code is being executed. It's a bit more to type but I type it so often that I can now type it *really fast*. Oscar -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On 18/11/2013 09:50, Oscar Benjamin wrote: On 17 November 2013 13:33, Roy Smith r...@panix.com wrote: So, I stick assert 0 in the code an re-run the program to see if I get an AssertionError. If I do, then I know the code is being run. If I don't then I know it's not. Either way, I know more about what's going on than I did before. Once I know what's going on, I remove the assert. If the program is invoked from a terminal I would probably go with 'import pdb; pdb.set_trace()' rather than 'assert 0'. Then you can check much more than whether or not the code is being executed. It's a bit more to type but I type it so often that I can now type it *really fast*. Oscar If I used something that often I'd either cut and paste it or have a key combination set up to insert it automatically. Or get my man to type it up for me :) -- Python is the second best programming language in the world. But the best has yet to be invented. Christian Tismer Mark Lawrence -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On 2013-11-18 09:50, Oscar Benjamin wrote: If the program is invoked from a terminal I would probably go with 'import pdb; pdb.set_trace()' rather than 'assert 0'. Then you can check much more than whether or not the code is being executed. It's a bit more to type but I type it so often that I can now type it *really fast*. I do this so much that on my main development machines, I have a line in my vimrc file nnoremap leaderp oimport pdb; pdb.set_trace()esc nnoremap leaderP Oimport pdb; pdb.set_trace()esc which maps the the leader key (defaults to \) followed by p/P to insert the pdb line below/above the current line. Saves bunches of time hassle. I'm sure it's equally easy in other quality editors. -tkc -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On 2013-11-17 07:35, Steven D'Aprano wrote: py x = 23 py assert x 0, x is not zero or negative This is the worst way to use an assertion: with a misleading message ;-) -tkc -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
In article 528871d5$0$29975$c3e8da3$54964...@news.astraweb.com, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: * Don't use assert for any error which you expect to recover from. In other words, you've got no reason to catch an AssertionError exception in production code. Which leads to another reason for using asserts... Every once in a while, I'll get into a situation where something is happening that I just can't understand. If a given pice of code is being called, there's NO WAY the program should be exhibiting the behavior it's exhibiting. But, there's also NO WAY that piece of code can't be getting called. So, I stick assert 0 in the code an re-run the program to see if I get an AssertionError. If I do, then I know the code is being run. If I don't then I know it's not. Either way, I know more about what's going on than I did before. Once I know what's going on, I remove the assert. -- https://mail.python.org/mailman/listinfo/python-list
Re: When to use assert
On Sun, 17 Nov 2013 06:50:56 -0600, Tim Chase wrote: On 2013-11-17 07:35, Steven D'Aprano wrote: py x = 23 py assert x 0, x is not zero or negative This is the worst way to use an assertion: with a misleading message ;-) D'oh! Sorry about that. -- Steven -- https://mail.python.org/mailman/listinfo/python-list
When to use assert
The question of when to use the assert statement comes up occasionally, usually in response to somebody misusing it, so I thought I'd write a post describing when and why to use assertions, and when not to. For those who aren't aware of it, Python's assert checks a condition, if it is true it does nothing, and if it is false it raises an AssertionError with an optional error message. For example: py x = 23 py assert x 0, x is not zero or negative py assert x%2 == 0, x is not an even number Traceback (most recent call last): File stdin, line 1, in module AssertionError: x is not an even number Many people use asserts as a quick and easy way to raise an exception if an argument is given the wrong value. But this is wrong, dangerously wrong, for two reasons. The first is that AssertionError is usually the wrong error to give when testing function arguments. You wouldn't write code like this: if not isinstance(x, int): raise AssertionError(not an int) you'd raise TypeError instead. assert raises the wrong sort of exception. But, and more dangerously, there's a twist with assert: it can be compiled away and never executed, if you run Python with the -O or -OO optimization flags, and consequently there is no guarantee that assert statements will actually be run. 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. When should use assert? In no particular order, assertions should be used for: * defensive programming; * runtime checks on program logic; * checking contracts (e.g. pre-conditions and post-conditions); * program invariants; and * checked documentation. (It's also acceptable to use assert when testing code, as a sort of quick- and-dirty poor man's unit testing, so long as you accept that the tests simply won't do anything if you run with the -O flag. And I sometimes use assert False in code to mark code branches that haven't been written yet, and I want them to fail. Although raise NotImplementedError is probably better for that, if a little more verbose.) Opinions on assertions vary, because they can be a statement of confidence about the correctness of the code. If you're certain that the code is correct, then assertions are pointless, since they will never fail and you can safely remove them. If you're certain the checks can fail (e.g. when testing input data provided by the user), then you dare not use assert since it may be compiled away and then your checks will be skipped. It's the situations in between those two that are interesting, times when you're certain the code is correct but not *quite* absolutely certain. Perhaps you've missed some odd corner case (we're all only human). In this case an extra runtime check helps reassure you that any errors will be caught as early as possible rather than in distant parts of the code. (This is why assert can be divisive. Since we vary in our confidence about the correctness of code, one person's useful assert is another person's useless runtime test.) Another good use for asserts is checking program invariants. An invariant is some condition which you can rely on to be true unless a bug causes it to become false. If there's a bug, better to find out as early as possible, so we make a test for it, but we don't want to slow the code down with such tests. Hence assert, which can be turned on in development and off in production. An example of an invariant might be, if your function expects a database connection to be open when it starts, and promises that it will still be open when it returns, that's an invariant of the function: def some_function(arg): assert not DB.closed() ... # code goes here assert not DB.closed() return result Assertions also make good checked comments. Instead of writing a comment: # when we reach here, we know that n 2 you can ensure it is checked at runtime by turning it into an assert: assert n 2 Assertions are also a form of defensive programming. You're not protecting against errors in the code as it is now, but protecting against changes which introduce errors later. Ideally, unit tests will pick those up, but let's face it, even when tests exist at all, they're often incomplete. Build-bots can be down and nobody notices for weeks, or people forget to run tests before committing code. Having an internal check is another line of defence against errors sneaking in, especially those which don't noisily fail but cause the code to malfunction and return incorrect results. Suppose you have a series of if...elif blocks, where you know ahead of time what values some variable is expected to have: # target is expected to be one of x, y, or z, and nothing else. if target == x: run_x_code() elif target == y: run_y_code() else: run_z_code() Assume that this code is completely correct now. But will it stay correct