On Aug 20, 10:13 pm, Steven D'Aprano <[EMAIL PROTECTED] cybersource.com.au> wrote: > It might not be enjoyable to have a sarcastic remark directed your way, > but it isn't a personal attack. Just because a comment is about something > you do doesn't make it a personal attack. Personal attacks are about who > you are rather than what you do.
If you type in "Personal Attack" in Wikipedia (not an authoritative source, I know) it takes you to the page on ad hominem arguments. There you can find the following example of the fallacious ad hominem argument: Person A makes claim X There is something objectionable about Person A Therefore claim X is false It is, ultimately, a matter of opinion, but "going out of one's way to make it hard for other programmers" sounds objectionable to me. I mean, I wouldn't want to work with anyone like that! > There's an apparent contradiction in your argument. You seem to be > arguing against EAFP and in favour of LBYL, but now you're suggesting > that you don't use type-checking. As near as I can tell, you don't do > type-checking, you don't do duck typing, you don't like catching > exceptions. So what do you actually do to deal with invalid data? Here is an example from a Django web app: when there is a bug, a generic Exception is thrown and Django catches it and reports a beautifully formatted stack trace. When something must be reported to the user, a MyAppException is thrown (not the real name). The HTTP request handler for the application is wrapped in a single try:... except MyAppException:.... the big idea is that there should be a maximum of two try/except blocks on the stack at any particular point in time [1]: at a high level (already mentioned) and for wrapping primitive "execute" operations against Rpy and MySQLdb. In practice, this doesn't always happen - there is one place where an EAFP-style construct is used (the "operation" in this case is to generate some HTML and cache it based on some source XML, but the source may have "syntax errors", so if the HTML can't be generated, then cleanup is performed and an error message returned). So to summarize: try/except blocks at boundaries between system components: good try/except blocks within a single component: slightly concerning I think I may have overstated the case against EAFP. There are certainly cases where EAFP makes a lot of sense; I would object to portraying EAFP as an alternative to defensive programming. [Side note: defensive programming serves much the same purpose in Python as it does in C, but I agree that in C there is extra motivation such as avoiding buffer overruns. I think of defensive programming simply as "taking proactive steps to reduce the expected time to debug a program if a programming error should arise".] > By the way, if you're worried that isinstance() is too long to type, you > can do this: > > isin = isinstance > isin(123, int) Actually I'm holding out for type objects to grow __lt__ and __le__ methods so you can do something like from abstract_base_classes import sequence if type(my_obj) <= sequence: ... This is borrowed from the <= notation for subgroups in math (there are probably other cases too). I don't use abstract base classes, so I don't even know if this is right, but hopefully you get the idea. > No no no, exceptions are not necessarily bugs!!! A bug is an exceptional > circumstance, but not all exceptional circumstances are bugs. I tend to agree, but I have found that thinking about these issues makes me question the wisdom of Python's built-ins throwing exceptions in non-exceptional circumstances (for instance you try to open a file that doesn't exist - IMHO this is about as exceptional as trying a no- wait acquire on a busy lock, in other words it isn't exceptional at all). As long as we are in fantasy realm, one could argue that open() should return a pair like this: f, open_ok = open(...) where open_ok is a status object whose __nonzero__ (in 3.0 __bool__ is used) is true on success and false on an error, and also has an error code and error message field. The idea is from Django's get_or_create method in the db API. [1] That I have to think about. I don't particularly care about try/ except blocks in Django's, Rpy's, or MySQLdb's activation records. David -- http://mail.python.org/mailman/listinfo/python-list