> On 7/17/2012 8:01 AM, Lipska the Kat wrote:
>> In bash this is laughably trivial
>> sort -nr $1 | head -${2:-10}
> Won't sort work alphabetically and leave the following as is?
> 1\talpha
> 11\tbeta
> 2\tgamma
Only if Lipska had omitted the "-n" which tells sort to treat
numbers like numbers.
For Lipska, you'd want to look into the "csv" module for parsing the
file easily (specifying '\t' as the delimiter). You can then sort
and crop as-is, or you can use heapq.nsmallest()
> (In some ways, it is already better than 3.2.3.)
I certainly make heavy use of some of the new features. I'm not sure we
can have enough separate exceptions for OS errors without exhausting
every possibility and I might start looking for excuses to use the lzma
module. :P
<lip...@lipskathekat.com> wrote:
> Well 'type-bondage' is a strange way of thinking about compile time type
> checking and making code easier to read (and therefor debug) but
> I'm not about to get into some religious war about declaring a variables
> type.
There are options for that, but they aren't Python. (I'd like to see a
"from __future__ import variable_declarations", but it doesn't seem to
work. Yet.) If you're interested, I could tell you about a language
that has a lot of what you're looking for (including polymorphism and
even the ability to declare a variable that can contain "non-negative
integer" as a type), but it's off-topic for the forum. However, I
can't email you, as lipskathekat.com doesn't seem to exist... Email me
privately if you're interested, we can continue the discussion
off-list.
> Terry Reedy wrote:
>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>> Well 'type-bondage' is a strange way of thinking about compile time type
>>> checking and making code easier to read (and therefor debug
>> 'type-bondage' is the requirement to restrict function inputs and output >> to one declared type, where the type declaration mechanisms are usually >> quite limited.
>> >>> def max(a, b):
>> if a <= b: return a
>> return b
> Surely you meant 'if a >= b: . . .'
> No worries, I'm sure your unittests would have caught it. ;)
> Terry Reedy wrote:
>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>> Well 'type-bondage' is a strange way of thinking about compile time type
>>> checking and making code easier to read (and therefor debug
>> 'type-bondage' is the requirement to restrict function inputs and
>> output to one declared type, where the type declaration mechanisms are
>> usually quite limited.
>> >>> def max(a, b):
>> if a <= b: return a
>> return b
> Surely you meant 'if a >= b: . . .'
> No worries, I'm sure your unittests would have caught it. ;)
> ~Ethan~
Wouldn't the compiler have caught it before the unittests? :-)
> On 7/17/2012 8:01 AM, Lipska the Kat wrote:
>> On 17/07/12 09:45, Lipska the Kat wrote:
>>> Pythoners
>>> Python 2.7.3
>>> Ubuntu Linux 12.04 LTS
>>> I've been taking a brief look at Python.
>> snip
>> Well I've set myself a task.
>> I have a text file containing a list of stock items
>> each line contains the number in stock followed by a tab followed by the
>> name of the item. I need to implement something that reads in the text
>> file and outputs the stock list in ascending or descending order of
>> quantity.
snip
>> In bash this is laughably trivial
>> sort -nr $1 | head -${2:-10}
> Won't sort work alphabetically and leave the following as is?
> 1\talpha
> 11\tbeta
> 2\tgamma
The -n option tells sort to interpret the first word on a line as a number r means sort in descending order. It works fine. I also added another feature not in the specification that allows the input of a number of lines to print ...
well on the way to being bloatware I guess ;-)
Lipska
-- Lipska the Kat: Troll hunter, Sandbox destroyer
and Farscape dreamer of Aeryn Sun.
> On 17/07/2012 18:29, Ethan Furman wrote:
>> Terry Reedy wrote:
>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>>> Well 'type-bondage' is a strange way of thinking about compile time
>>>> type
>>>> checking and making code easier to read (and therefor debug
>>> 'type-bondage' is the requirement to restrict function inputs and
>>> output to one declared type, where the type declaration mechanisms are
>>> usually quite limited.
>>> >>> def max(a, b):
>>> if a <= b: return a
>>> return b
>> Surely you meant 'if a >= b: . . .'
>> No worries, I'm sure your unittests would have caught it. ;)
>> ~Ethan~
> Wouldn't the compiler have caught it before the unittests? :-)
Not unless the compiler could read your mind!
The syntax looks fine it's the semantics that are suspect. Wrong is a word that I try not to use as it tends to upset people, let's call them "differently right" ;-)
BTW having more than one return statement in a block is a little thing I know but it drives me nuts ... another "Pythonic" thing I'll have to get used to I suppose.
-- Lipska the Kat: Troll hunter, Sandbox destroyer
and Farscape dreamer of Aeryn Sun.
Mark Lawrence wrote:
> On 17/07/2012 18:29, Ethan Furman wrote:
>> Terry Reedy wrote:
>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>>> Well 'type-bondage' is a strange way of thinking about compile time >>>> type
>>>> checking and making code easier to read (and therefor debug
>>> 'type-bondage' is the requirement to restrict function inputs and
>>> output to one declared type, where the type declaration mechanisms are
>>> usually quite limited.
>>> >>> def max(a, b):
>>> if a <= b: return a
>>> return b
>> Surely you meant 'if a >= b: . . .'
>> No worries, I'm sure your unittests would have caught it. ;)
>> ~Ethan~
> Wouldn't the compiler have caught it before the unittests? :-)
Silly me, the word processor would have caught it!
On Tue, Jul 17, 2012 at 1:07 PM, Terry Reedy <tjre...@udel.edu> wrote:
> 'type-bondage' is the requirement to restrict function inputs and output to
> one declared type, where the type declaration mechanisms are usually quite
> limited.
This is interesting, I hadn't expected that sort of definition. So
Haskell is not a type-bondage language?
(i.e. it lets you write functions that accept any type via parametric
polymorphism, or any type that supports an interface via type
classes).
> How easy was it to write max, or a universal sort in Java?
You write obj.compareTo(other) < 0 instead of using obj < other, and
your methods only work on objects (that support the comparable
interface). Otherwise, no different than Python, I guess.
Would Java not be a type-bondage language if everything was an object?
>> Well 'type-bondage' is a strange way of thinking about compile time type
>> checking and making code easier to read (and therefor debug
snip
> How easy was it to write max, or a universal sort in Java?
Well java.lang.Math.max() (or min() depending on what you want) might do it and as for sorting ... java.utils.Collections.sort will sort anything that implements the java.util.Comparable interface. All the standard numerical classes implement Comparable by default so there is nothing to do really.
Lipska
-- Lipska the Kat: Troll hunter, Sandbox destroyer
and Farscape dreamer of Aeryn Sun.
> Mark Lawrence wrote:
>> On 17/07/2012 18:29, Ethan Furman wrote:
>>> Terry Reedy wrote:
>>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>>>> Well 'type-bondage' is a strange way of thinking about compile time
>>>>> type
>>>>> checking and making code easier to read (and therefor debug
>>>> 'type-bondage' is the requirement to restrict function inputs and
>>>> output to one declared type, where the type declaration mechanisms are
>>>> usually quite limited.
>>>> >>> def max(a, b):
>>>> if a <= b: return a
>>>> return b
>>> Surely you meant 'if a >= b: . . .'
>>> No worries, I'm sure your unittests would have caught it. ;)
>>> ~Ethan~
>> Wouldn't the compiler have caught it before the unittests? :-)
> Silly me, the word processor would have caught it!
> On 17/07/12 18:07, Terry Reedy wrote:
>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>> Well 'type-bondage' is a strange way of thinking about compile time type
>>> checking and making code easier to read (and therefor debug
> snip
>> How easy was it to write max, or a universal sort in Java?
> Well java.lang.Math.max() (or min() depending on what you want) might do
> it and as for sorting ... java.utils.Collections.sort will sort anything
> that implements the java.util.Comparable interface. All the standard
> numerical classes implement Comparable by default so there is nothing to
> do really.
> Lipska
I would like to spend more time on this thread, but unfortunately the 44 ton artic carrying "Java in a Nutshell Volume 1 Part 1 Chapter 1 Paragraph 1 Sentence 1" has just arrived outside my abode and needs unloading :-)
> Mark Lawrence wrote:
>> On 17/07/2012 18:29, Ethan Furman wrote:
>>> Terry Reedy wrote:
>>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>>>> Well 'type-bondage' is a strange way of thinking about compile >>>>> time type
>>>>> checking and making code easier to read (and therefor debug
>>>> 'type-bondage' is the requirement to restrict function inputs and
>>>> output to one declared type, where the type declaration mechanisms are
>>>> usually quite limited.
>>>> >>> def max(a, b):
>>>> if a <= b: return a
>>>> return b
>>> Surely you meant 'if a >= b: . . .'
>>> No worries, I'm sure your unittests would have caught it. ;)
>>> ~Ethan~
>> Wouldn't the compiler have caught it before the unittests? :-)
> Silly me, the word processor would have caught it!
> ~Ethan~
No compiler can find as many faults as publishing your code on a mailing list!!!
:)
> On 17/07/2012 20:29, Lipska the Kat wrote:
>> On 17/07/12 18:07, Terry Reedy wrote:
>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
snip
>>> How easy was it to write max, or a universal sort in Java?
>> Well java.lang.Math.max() (or min() depending on what you want) might do
>> it and as for sorting ... java.utils.Collections.sort will sort anything
>> that implements the java.util.Comparable interface. All the standard
>> numerical classes implement Comparable by default so there is nothing to
>> do really.
>> Lipska
> I would like to spend more time on this thread, but unfortunately the 44
> ton artic carrying "Java in a Nutshell Volume 1 Part 1 Chapter 1
> Paragraph 1 Sentence 1" has just arrived outside my abode and needs
> unloading :-)
:-)))))))
LOL (and I did) but the pay is FANTASTIC, particularly if you 'get' OO.
-- Lipska the Kat: Troll hunter, Sandbox destroyer
and Farscape dreamer of Aeryn Sun.
> On 17/07/12 19:18, Mark Lawrence wrote:
>> On 17/07/2012 18:29, Ethan Furman wrote:
>>> Terry Reedy wrote:
>>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
>>>>> Well 'type-bondage' is a strange way of thinking about compile time
>>>>> type
>>>>> checking and making code easier to read (and therefor debug
>>>> 'type-bondage' is the requirement to restrict function inputs and
>>>> output to one declared type, where the type declaration mechanisms are
>>>> usually quite limited.
>>>> >>> def max(a, b):
>>>> if a <= b: return a
>>>> return b
>>> Surely you meant 'if a >= b: . . .'
>>> No worries, I'm sure your unittests would have caught it. ;)
>>> ~Ethan~
>> Wouldn't the compiler have caught it before the unittests? :-)
> Not unless the compiler could read your mind!
> The syntax looks fine it's the semantics that are suspect. Wrong is a
> word that I try not to use as it tends to upset people, let's call them
> "differently right" ;-)
> BTW having more than one return statement in a block is a little thing I
> know but it drives me nuts ... another "Pythonic" thing I'll have to get
> used to I suppose.
Its not a pythonic thing. Its a common and very acceptable paradigm.
Mainly, it avoids complicated breaks from nested control structures, and
especially the 'style' of maintaining one boolean value called
"should_continue" or something equally silly.
My daily work involves C, x86 assembly, reading x86/PCI/ACPI/etc
specifications and cursing violently at some of the stupidity, Python,
Bash and C++, and this is one of the few styles which remains fairly
constant throughout.
Take for example a Linux system call handler. The general form looks a
little like (substituting C for python style pseudocode)
if not (you are permitted to do this):
return -EPERM
if not (you've given me some valid data):
return -EFAULT
if not (you've given me some sensible data):
return -EINVAL
return actually_try_to_do_something_with(data)
How would you program this sort of logic with a single return statement?
This is very common logic for all routines for which there is even the
remotest possibility that some data has come from an untrusted source.
> > On 17/07/12 19:18, Mark Lawrence wrote:
> >> On 17/07/2012 18:29, Ethan Furman wrote:
> >>> Terry Reedy wrote:
> >>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
> >>>>> Well 'type-bondage' is a strange way of thinking about compile time
> >>>>> type
> >>>>> checking and making code easier to read (and therefor debug
> >>>> 'type-bondage' is the requirement to restrict function inputs and
> >>>> output to one declared type, where the type declaration mechanisms are
> >>>> usually quite limited.
> >>>> >>> def max(a, b):
> >>>> if a <= b: return a
> >>>> return b
> >>> Surely you meant 'if a >= b: . . .'
> >>> No worries, I'm sure your unittests would have caught it. ;)
> >>> ~Ethan~
> >> Wouldn't the compiler have caught it before the unittests? :-)
> > Not unless the compiler could read your mind!
> > The syntax looks fine it's the semantics that are suspect. Wrong is a
> > word that I try not to use as it tends to upset people, let's call them
> > "differently right" ;-)
> > BTW having more than one return statement in a block is a little thing I
> > know but it drives me nuts ... another "Pythonic" thing I'll have to get
> > used to I suppose.
> Its not a pythonic thing. Its a common and very acceptable paradigm.
> Mainly, it avoids complicated breaks from nested control structures, and
> especially the 'style' of maintaining one boolean value called
> "should_continue" or something equally silly.
> My daily work involves C, x86 assembly, reading x86/PCI/ACPI/etc
> specifications and cursing violently at some of the stupidity, Python,
> Bash and C++, and this is one of the few styles which remains fairly
> constant throughout.
> Take for example a Linux system call handler. The general form looks a
> little like (substituting C for python style pseudocode)
> if not (you are permitted to do this):
> return -EPERM
> if not (you've given me some valid data):
> return -EFAULT
> if not (you've given me some sensible data):
> return -EINVAL
> return actually_try_to_do_something_with(data)
> How would you program this sort of logic with a single return statement?
> This is very common logic for all routines for which there is even the
> remotest possibility that some data has come from an untrusted source.
return (-EPERM if not_permitted else -EFAULT if non_valid else -EINVAL
if non_sensible else do_something)
Not that I recommend *doing* this :-)
[I recommend knowing about it]
> Thanks for your time and I'll try to do a bit better with the reading thing before asking more
> questions... not sure about this obsession with code indentation though :-|
I think it's inaccurate to call this indentation an obsession, it's part of Python's defined syntax. It's used INSTEAD OF punctuation or keywords (like {} or BEGIN END). If you're already used to indenting your code consistently, you'll be surprised at how quickly it becomes a non-issue when you start using Python.
> On 17/07/2012 19:36, Lipska the Kat wrote:
>> On 17/07/12 19:18, Mark Lawrence wrote:
>>> On 17/07/2012 18:29, Ethan Furman wrote:
>>>> Terry Reedy wrote:
>>>>> On 7/17/2012 10:23 AM, Lipska the Kat wrote:
snip
> Take for example a Linux system call handler. The general form looks a
> little like (substituting C for python style pseudocode)
> if not (you are permitted to do this):
> return -EPERM
> if not (you've given me some valid data):
> return -EFAULT
> if not (you've given me some sensible data):
> return -EINVAL
> return actually_try_to_do_something_with(data)
> How would you program this sort of logic with a single return statement?
> This is very common logic for all routines for which there is even the
> remotest possibility that some data has come from an untrusted source.
someType result = -EINVAL //or your most likely or 'safest' result
if not (you are permitted to do this):
result = -EPERM
if not (you've given me some valid data):
result = -EFAULT
if not (you've given me some sensible data):
result = -EINVAL
else
result = -EDSOMETHING
return result
}
//cohesive, encapsulated, reusable and easy to read
//later
if(checkSomething(data) == EDOSOMETHING){
actually_try_to_do_something_with(data)
}
else{
//who knows
}
What do you think ?
> ~Andrew
> P.S. like the sig.
thanks
-- Lipska the Kat: Troll hunter, Sandbox destroyer
and Farscape dreamer of Aeryn Sun.
On 17 July 2012 13:01, Lipska the Kat <lip...@lipskathekat.com> wrote:
> Well I've set myself a task.
> I have a text file containing a list of stock items
> each line contains the number in stock followed by a tab followed by the
> name of the item. I need to implement something that reads in the text file
> and outputs the stock list in ascending or descending order of quantity.
> Please note I am NOT asking for solutions.
> In bash this is laughably trivial
> sort -nr $1 | head -${2:-10}
Here's a Python translation that won't help :)
from sys import argv
print ''.join(sorted(open(argv[1]), key=lambda l:
-int(l.split('\t')[0]))[:10 if len(argv) < 3 else int(argv[2])])
> On 18/07/12 01:46, Andrew Cooper wrote:
>> Take for example a Linux system call handler. The general form looks a
>> little like (substituting C for python style pseudocode)
>> if not (you are permitted to do this):
>> return -EPERM
>> if not (you've given me some valid data):
>> return -EFAULT
>> if not (you've given me some sensible data):
>> return -EINVAL
>> return actually_try_to_do_something_with(data)
>> How would you program this sort of logic with a single return statement?
>> This is very common logic for all routines for which there is even the
>> remotest possibility that some data has come from an untrusted source.
> someType result = -EINVAL //or your most likely or 'safest' result
> if not (you are permitted to do this):
> result = -EPERM
> if not (you've given me some valid data):
> result = -EFAULT
> if not (you've given me some sensible data):
> result = -EINVAL
> else
> result = -EDSOMETHING
> return result
> }
> //cohesive, encapsulated, reusable and easy to read
This is a classic discussion topic, whether single exit (SE) functions should be used or not. There are two things I consider as problematic with them:
1. In the presence of exceptions, every function has at least two possible paths that can be taken out, one returns a value (or None, in Python), the other throws an exception. For that reason, trying to achieve SE is a dangerous illusion. The syscall handler above is C, which doesn't have exceptions like Java, C++ or Python, so it doesn't suffer those two paths.
2. The biggest problem with SE functions is that you often need to skip over lots of code before you finally find out that the fault at the very beginning causes nothing else to happen inside the function before it is finally returned to the caller. A typical symptom is deeply nested if-else structures. Another symptom is result variables that are checked multiple times to skip over effectively the rest of the function, which "unrolls" the nested if-else structures. Yet another symptom is a very fine granularity of microscopic functions, which is effectively a distributed nest of if-else structures.
Coming back to Python, this would look like this:
if not /you are permitted to do this/:
raise NotPermitted("go awai!")
if not /you've given me valid data/:
raise TypeError("unexpected input")
if not /you're given me sensible data/:
raise ValueError("invalid input")
# do stuff here...
If you shoehorn this into an SE function (which you can't do if something in between might throw), then it probably looks like this:
error = None
if not /you are permitted to do this/:
error = NotPermitted("go awai!")
elif not /you've given me valid data/:
raise TypeError("unexpected input")
elif not /you're given me sensible data/:
raise ValueError("invalid input")
else:
# do stuff here...
if error:
raise error
else:
return result
Interestingly, you suggest to divide the original function into one that verifies some conditions and one that does the actual work. Using an early return is to me like drawing a big red line inside a function by which it can be split into two sections. This makes it IMHO equally clear, even clearer since I don't have to locate and read that other function. My bioware parses this so that if the first part succeeds, the second part can be read independently thereof, which reduces the amount of info to keep in mind at a time.
Also, when changing code, I don't have to locate other places where the utility function (checkSomething) is called (Python allows local functions, which can be very(!!) useful). Since the code is inline, I know that only this one function is affected. Yes, this is in direct contrast to the reusability you mentioned. Neither ease of change nor reusability are goals in and of themselves though, so this is not a black-or-white question and a compromise can be good enough. It's a question of taste, experience, phase of the moon, coffeination levels etc.
On Tue, 17 Jul 2012 12:01:21 +0100, Lipska the Kat wrote:
> For the past 9 years I have been developing in Java
[...]
> Anyway, I'm looking at Python as a rapid prototyping language. I have an
> idea and just want to get it down in basic outline code as quickly as
> possible before it departs my aging brain...
A couple of good resources for you to read, written by a top Python developer who also knows Java backwards:
You will occasionally (i.e. about sixteen times a day) read some Python programmer tossing out comments like "Flat is better than nested", often in quotes. P.J. Eby does this at least twice in the first link above. What the hell are they talking about?
They're talking about the Zen of Python, a list of a dozen or so slightly tongue in cheek mottoes meant to encapsulate the (often deliberately contradictory) coding philosophy that Python developers should aspire too. At the interactive Python prompt, enter "import this" (without the quotes) and be enlightened.
Keeping the Zen in mind as an ideal is incredibly useful. Arguing over whose opinion is more true to the Zen is a waste of time.
> I'm not used to using
> variables without declaring their type ... (well I used to do Visual
> Basic many years ago) It just seems so weird,
Compared to Java, or Haskell, or Ada, Python may seem like an incredibly sloppy language. A lot of that sloppiness comes from the lack of compile-
time type-checking. And that's probably true: Haskell's type checker can detect infinite loops, by Jove! Python won't even warn you that you're about to blow away a built-in function. (Don't worry though, you can easily get it back again.)
(But at least Python isn't Perl, or PHP.)
While Python doesn't (can't!) check the type of data at compile-time, but it does check the type of data at run-time. This ain't assembly language, where there's only one type, bytes! I came from a Pascal background, and at first I found the lack of type declarations rather concerning. But soon I found it liberating.
Especially once I started using Python interactively, at the REPL.
Most arguments about which is better, compile-time type checking or run-
time type checking, miss the point: both have advantages, and disadvantages. Which is "better" depends on what you want to do.
Python is deliberately designed to be *fast to write*. It gives up a little bit of safety for that. But not as much as you might think. Type errors are less frequent than other errors (errors of logic, bad data, etc.). And so in the time it might take a Java programmer to satisfy the compiler's insistence on type correctness, a Python programmer has probably written the program *and* the unittests and given the customer the first iteration of the application.
At least, that's the theory.
But you probably already know that. After all, that's why Python is the rapid-application-development language, not Java.
> and what's this obsession
> with 'correct' indentation of code ???
Nearly everyone rights correctly indented code anyway. At least, those who don't, you don't want on your project. Python just takes it one step further, and makes correctly indented code mandatory rather than optional.
The plus side is, no more style wars over where the braces go, no more hunting for lost braces. The downside is, if you paste code into a dumb application (like many email clients!) that strips whitespace, your code will break. So don't do that.
On Tue, 17 Jul 2012 09:52:59 -0400, Roy Smith wrote:
> you could write in Python:
> # Type matching will get checked at run-time > def my_function(mpf, ot):
> assert isinstance(mpf, MassivelyParallelFrobinator) > assert isinstance(ot, OtherThing)
Keep in mind that assertions are not guaranteed to run. Code like the above is buggy, because if Python is run under the -O (optimize) flag, assertions will be stripped out.
Assertions are mostly useful for two things:
1) "This cannot possibly happen, but just in case it does..."
If you've ever written something like this:
if x%2 == 0:
do_spam()
elif x%2 == 1:
do_ham()
else:
# This can't happen!
print("something unexpected happened")
sys.exit()
2) To check your internal reasoning in a function or method.
For example:
def foo(something):
n = len(something)
x = math.sqrt(x)
# We expect that x must be less than half of n. # E.g. n=100 gives 10 < 50, which is correct.
assert x < n//2
process(n, x)
Run with the -O flag, the (hopefully!) redundant test will be stripped out; without the flag, the test will check your logic for you and fail if the stated condition is not met.
For bonus points, can you see the mistake? The stated condition is wrong. Without the assert, the process() code could go off and potentially silently do the wrong thing, but the assert guards against that possibility. And once I've had a bug report that my app raises an AssertionError, I will go back and think more carefully about the assertion that sqrt(n) is always less than half of n.
> but that's just not the way people write code in Python.
Better is to use explicit type checks and raise an exception yourself:
if not isinstance(x, int):
raise TypeError('expected an int, got %r' % x)
On Wed, 18 Jul 2012 01:46:31 +0100, Andrew Cooper wrote:
> Take for example a Linux system call handler. The general form looks a
> little like (substituting C for python style pseudocode)
> if not (you are permitted to do this):
> return -EPERM
> if not (you've given me some valid data):
> return -EFAULT
> if not (you've given me some sensible data):
> return -EINVAL
> return actually_try_to_do_something_with(data)
> How would you program this sort of logic with a single return statement?
That's not terribly hard.
if not (you are permitted to do this):
result = -EPERM
elif not (you've given me some valid data):
result = -EFAULT
elif not (you've given me some sensible data):
result = -EINVAL
else:
result = actually_try_to_do_something_with(data)
return result
A better example would involve loops. I used to hate programming in some versions of Pascal without a break statement: I needed a guard variable to decide whether or not to do anything in the loop!
# pseudo-code
for i in 1 to 100:
if not condition:
do_something_useful()
Even with a break, why bother continuing through the body of the function when you already have the result? When your calculation is done, it's done, just return for goodness sake. You wouldn't write a search that keeps going after you've found the value that you want, out of some misplaced sense that you have to look at every value. Why write code with unnecessary guard values and temporary variables out of a misplaced sense that functions must only have one exit?
In article <5006b2e2$0$29978$c3e8da3$54964...@news.astraweb.com>,
Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> wrote:
> On Tue, 17 Jul 2012 09:52:59 -0400, Roy Smith wrote:
> > you could write in Python:
> > # Type matching will get checked at run-time > > def my_function(mpf, ot):
> > assert isinstance(mpf, MassivelyParallelFrobinator) > > assert isinstance(ot, OtherThing)
> Keep in mind that assertions are not guaranteed to run. Code like the > above is buggy, because if Python is run under the -O (optimize) flag, > assertions will be stripped out.
One could equally say that "code like the above is efficient, because if Python is run under the -O (optimize) flag, assertions will be stripped out" :-)
> Better is to use explicit type checks and raise an exception yourself:
> if not isinstance(x, int):
> raise TypeError('expected an int, got %r' % x)
Maybe, but that's two lines where one does just fine. If you're going to go for type-bondage, you might as well be efficient and succinct about it.
On Wed, 18 Jul 2012 09:07:22 -0400, Roy Smith wrote:
>> Keep in mind that assertions are not guaranteed to run. Code like the
>> above is buggy, because if Python is run under the -O (optimize) flag,
>> assertions will be stripped out.
> One could equally say that "code like the above is efficient, because if
> Python is run under the -O (optimize) flag, assertions will be stripped
> out" :-)
You seem to have missed my point. Asserts *should* be used for checks which are optional. In this case, the fact that assert is optimized away is a feature: you have the added safety of a guard against some programming errors, while still being able to optimize that code on request. This is what assert is for. You get no argument from me about that -- my code is bulging with assertions.
But where you *need* an explicit check to run, assert is not suitable, because you cannot control whether or not it will run. The caller, not you, controls that, by passing -O to the python interpreter.
If you have a public function or method that can be called by any other piece of code, and it has required pre-conditions that need to be checked (not necessarily a type-check), then DO NOT USE ASSERT.
If you use assert, then sometimes that pre-condition will not happen, and the caller can pass garbage into your function. The pre-condition will be violated, and your function will silently go off and do the wrong thing without warning.
If you're lucky, your program will fail somewhere else, probably far away from where the error actually occurs, and you will merely have to spend hours or days trying to debug it.
If you're unlucky, your program won't fail, it will just calculate garbage, or otherwise do the wrong thing.
Besides, there is another reason not to use assert: it gives the wrong exception. If the error is a type error, you should raise TypeError, not ValueError, or ZeroDivisionError, or IndexError, or AssertionError. Using assert because it saves a line of code is lazy, sloppy programming.
>> Better is to use explicit type checks and raise an exception yourself:
>> if not isinstance(x, int):
>> raise TypeError('expected an int, got %r' % x)
> Maybe, but that's two lines where one does just fine.
But one line (assert) does *not* do just fine under the conditions I am talking about.
If you need the check to run, then assert is not suitable, because it is not guaranteed to run. It's as simple as that.