Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Python: Python

Clarity vs. code reuse/generality

 

 

First page Previous page 1 2 3 4 Next page Last page  View All Python python RSS feed   Index | Next | Previous | View Threaded


aahz at pythoncraft

Jul 7, 2009, 7:41 AM

Post #51 of 85 (883 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

In article <mailman.2765.1246971084.8015.python-list [at] python>,
Jean-Michel Pichavant <jeanmichel [at] sequans> wrote:
>
>Can't we just calm down ? I'm really sorry my ignorance started this
>thread, and my apologies go to Kj who's obviously more fluent in english
>than me.
>I've never used sense in that way before, nor I've seen used by others
>until now. However Kj is right, and my dictionary seems wrong
>(wordreference.com). I've searched through others dictionaries and find
>out this is actually applicable to functions. My bad.

You were not the first person to point out that "sense" is a poor
variable name. Unless KJ is specifically using this code in the context
of a math class, I still think that "sense" is completely inappropriate.
Your English fluency is just fine.
--
Aahz (aahz [at] pythoncraft) <*> http://www.pythoncraft.com/

"as long as we like the same operating system, things are cool." --piranha
--
http://mail.python.org/mailman/listinfo/python-list


sajmikins at gmail

Jul 7, 2009, 7:48 AM

Post #52 of 85 (883 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Tue, Jul 7, 2009 at 8:51 AM, Jean-Michel
Pichavant<jeanmichel [at] sequans> wrote:
> Steven D'Aprano wrote:
>>
>> On Tue, 07 Jul 2009 05:13:28 +0000, Lie Ryan wrote:
>>
>>
>>>
>>> When people are fighting over things like `sense`, although sense may
>>> not be strictly wrong dictionary-wise, it smells of something burning...
>>>
>>
>> That would be my patience.
>>
>> I can't believe the direction this discussion has taken. Anybody sensible
>> would be saying "Oh wow, I've just learned a new meaning to the word, that's
>> great, I'm now less ignorant than I was a minute ago". But oh no, we mustn't
>> use a standard meaning to a word, heaven forbid we disturb people's
>> ignorance by teaching them something new.
>>
>> It's as simple as this: using `sense` as a variable name to record the
>> sense of a function is not a code smell, any more than using `flag` to
>> record a flag would be, or `sign` to record the sign of an object. If you
>> don't know the appropriate meanings of the words sense, flag or sign, learn
>> them, don't dumb down my language.
>>
>>
>
> Can't we just calm down ? I'm really sorry my ignorance started this thread,
> and my apologies go to Kj who's obviously more fluent in english than me.
> I've never used sense in that way before, nor I've seen used by others until
> now. However Kj is right, and my dictionary seems wrong (wordreference.com).
> I've searched through others dictionaries and find out this is actually
> applicable to functions. My bad.
>
> JM

Well met, sir.
--
http://mail.python.org/mailman/listinfo/python-list


pdpinheiro at gmail

Jul 7, 2009, 11:01 AM

Post #53 of 85 (892 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Jul 7, 2:16 am, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.au> wrote:
> On Mon, 06 Jul 2009 16:43:43 +0100, Tim Rowe wrote:
> > 2009/7/4 kj <no.em...@please.post>:
>
> >> Precisely.  As I've stated elsewhere, this is an internal helper
> >> function, to be called only a few times under very well-specified
> >> conditions.  The assert statements checks that these conditions are as
> >> intended.  I.e. they are checks against the module writer's programming
> >> errors.
>
> > Good for you. I'm convinced that you have used the assertion
> > appropriately, and the fact that so many here are unable to see that
> > looks to me like a good case for teaching the right use of assertions.
> > For what it's worth, I read assertions at the beginning of a procedure
> > as part of the specification of the procedure, and I use them there in
> > order to document the procedure. An assertion in that position is for me
> > a statement to the user of the procedure "it's your responsibility to
> > make sure that you never call this procedure in such a way as to violate
> > these conditions". They're part of a contract, as somebody (maybe you)
> > pointed out.
>
> > As somebody who works in the safety-critical domain, it's refreshing to
> > see somebody teaching students to think about the circumstances in which
> > a procedure can legitimately be called. The hostility you've received to
> > that idea is saddening, and indicative of why there's so much buggy
> > software out there.
>
> LOL.
>
> Maybe the reason for "so much buggy software" is that people
> inappropriately use assert, thus changing the behaviour of code depending
> on whether it is run with the -O flag or not.
>
> I don't know what "hostility" you're seeing. The only hostility I'm
> seeing is from the OP, which is bizarre considering that he asked for
> advice and we gave it. What I see is a bunch of people concerned that the
> OP is teaching novices a bad habit, namely, using assert for error
> checking. He claims -- angrily and over and over again -- that in his
> code, the assertions should never fail. Great. Good for him for knowing
> when to use assert. (...)

But he doesn't.

He asserts:
assert lo < hi
but then compares:
sense = cmp(func(hi), func(lo))

sense can't ever be anything other than 1. I actually find it amusing
that this threat got to 50 posts of raving discussion about assertions
without anyone spotting that.

Personally, I think the code is an unreadable mess, but that's mostly
because of all the micro optimizations, not the generality of it.
Here's my unoptimized, but still equally generic, version:

def _binary_search(lo, hi, func, target, epsilon):
sense = cmp(func(hi), func(lo))
if sense == 0:
return None
guess = (lo + hi) / 2.
while abs(func(guess) - target) > epsilon:
guess = (lo + hi) / 2.
if func(guess) > target:
hi = guess
elif func(guess) < target:
lo = guess
elif lo == hi:
return None
return guess

This is a newbie course, right? A while True loop might be faster, but
it's all sorts of wrong for teaching newbies. Likewise, calculating a
midpoint as mid = (hi + lo) * .5 is an aberration in a beginner
environment. You want your students asking why you're calculating an
average, not asking why you're multiplying by 0.5. In the same vein, I
have no words for your target_plus/target_minus cleverness.

The right way to go about it, IMO, is to give them my version, let
them digest it, make all the necessary changes to it to turn it into
your (faster) version. Present benchmarks for both, then let the
readability/performance trade-off sink in. What you achieve with this
exercise is that, instead of making your students think "I have to
read that crud!?", they'll respect that ugly code is often the result
of eking out every last drop of performance from a program as you
possibly can.
--
http://mail.python.org/mailman/listinfo/python-list


http://phr.cx at NOSPAM

Jul 7, 2009, 11:06 AM

Post #54 of 85 (890 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

pdpi <pdpinheiro [at] gmail> writes:
> Personally, I think the code is an unreadable mess, but that's mostly
> because of all the micro optimizations, not the generality of it.
> Here's my unoptimized, but still equally generic, version:

That version doesn't use "sense" inside the binary search, i.e. it
relies on the function being monotonically increasing.
--
http://mail.python.org/mailman/listinfo/python-list


andreengels at gmail

Jul 7, 2009, 11:26 AM

Post #55 of 85 (883 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Tue, Jul 7, 2009 at 8:01 PM, pdpi<pdpinheiro [at] gmail> wrote:

> He asserts:
>    assert lo < hi
> but then compares:
>    sense = cmp(func(hi), func(lo))
>
> sense can't ever be anything other than 1.

It can - there is no necessity that func is monotonically increasing.

--
André Engels, andreengels [at] gmail
--
http://mail.python.org/mailman/listinfo/python-list


pdpinheiro at gmail

Jul 7, 2009, 11:30 AM

Post #56 of 85 (883 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Jul 7, 7:26 pm, Andre Engels <andreeng...@gmail.com> wrote:
> On Tue, Jul 7, 2009 at 8:01 PM, pdpi<pdpinhe...@gmail.com> wrote:
> > He asserts:
> >    assert lo < hi
> > but then compares:
> >    sense = cmp(func(hi), func(lo))
>
> > sense can't ever be anything other than 1.
>
> It can - there is no necessity that func is monotonically increasing.
>
> --
> André Engels, andreeng...@gmail.com

Yes, I realized that as I was walking home.

In other news, some of you may be interested in my seminar in advanced
foot-in-mouth placement.
--
http://mail.python.org/mailman/listinfo/python-list


pdpinheiro at gmail

Jul 7, 2009, 11:31 AM

Post #57 of 85 (885 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Jul 7, 7:06 pm, Paul Rubin <http://phr...@NOSPAM.invalid> wrote:
> pdpi <pdpinhe...@gmail.com> writes:
> > Personally, I think the code is an unreadable mess, but that's mostly
> > because of all the micro optimizations, not the generality of it.
> > Here's my unoptimized, but still equally generic, version:
>
> That version doesn't use "sense" inside the binary search, i.e. it
> relies on the function being monotonically increasing.

You're right, make that:

def _binary_search(lo, hi, func, target, epsilon):
sense = cmp(func(hi), func(lo))
if sense == 0:
return None
guess = (lo + hi) / 2.
while abs(func(guess) - target) > epsilon:
guess = (lo + hi) / 2.
if sense * func(guess) > target:
hi = guess
elif sense * func(guess) < target:
lo = guess
elif lo == hi:
return None
return guess

Seems I had a serious brain cramp while posting that...
--
http://mail.python.org/mailman/listinfo/python-list


pdpinheiro at gmail

Jul 7, 2009, 11:51 AM

Post #58 of 85 (883 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Jul 7, 7:31 pm, pdpi <pdpinhe...@gmail.com> wrote:
> On Jul 7, 7:06 pm, Paul Rubin <http://phr...@NOSPAM.invalid> wrote:
>
> > pdpi <pdpinhe...@gmail.com> writes:
> > > Personally, I think the code is an unreadable mess, but that's mostly
> > > because of all the micro optimizations, not the generality of it.
> > > Here's my unoptimized, but still equally generic, version:
>
> > That version doesn't use "sense" inside the binary search, i.e. it
> > relies on the function being monotonically increasing.
>
> You're right, make that:
>
> def _binary_search(lo, hi, func, target, epsilon):
>     sense = cmp(func(hi), func(lo))
>     if sense == 0:
>         return None
>     guess = (lo + hi) / 2.
>     while abs(func(guess) - target) > epsilon:
>         guess = (lo + hi) / 2.
>         if sense * func(guess) > target:
>             hi = guess
>         elif sense * func(guess) < target:
>             lo = guess
>         elif lo == hi:
>             return None
>     return guess
>
> Seems I had a serious brain cramp while posting that...

Actually, scratch that.

def _binary_search(lo, hi, func, target, epsilon):
sense = cmp(func(hi), func(lo))
if sense == 0:
return None
guess = (lo + hi) / 2.
while abs(func(guess) - target) > epsilon:
guess = (lo + hi) / 2.
if sense * func(guess) > sense * target:
hi = guess
elif sense * func(guess) < sense * target:
lo = guess
elif lo == hi:
return None
return guess
--
http://mail.python.org/mailman/listinfo/python-list


davea at ieee

Jul 7, 2009, 12:04 PM

Post #59 of 85 (883 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

pdpi wrote:
> On Jul 7, 2:16 am, Steven D'Aprano <st...@REMOVE-THIS-
> cybersource.com.au> wrote:
>
>> On Mon, 06 Jul 2009 16:43:43 +0100, Tim Rowe wrote:
>>
>>> 2009/7/4 kj <no.em...@please.post>:
>>>
>>>> Precisely. As I've stated elsewhere, this is an internal helper
>>>> function, to be called only a few times under very well-specified
>>>> conditions. The assert statements checks that these conditions are as
>>>> intended. I.e. they are checks against the module writer's programming
>>>> errors.
>>>>
>>> Good for you. I'm convinced that you have used the assertion
>>> appropriately, and the fact that so many here are unable to see that
>>> looks to me like a good case for teaching the right use of assertions.
>>> For what it's worth, I read assertions at the beginning of a procedure
>>> as part of the specification of the procedure, and I use them there in
>>> order to document the procedure. An assertion in that position is for me
>>> a statement to the user of the procedure "it's your responsibility to
>>> make sure that you never call this procedure in such a way as to violate
>>> these conditions". They're part of a contract, as somebody (maybe you)
>>> pointed out.
>>>
>>> As somebody who works in the safety-critical domain, it's refreshing to
>>> see somebody teaching students to think about the circumstances in which
>>> a procedure can legitimately be called. The hostility you've received to
>>> that idea is saddening, and indicative of why there's so much buggy
>>> software out there.
>>>
>> LOL.
>>
>> Maybe the reason for "so much buggy software" is that people
>> inappropriately use assert, thus changing the behaviour of code depending
>> on whether it is run with the -O flag or not.
>>
>> I don't know what "hostility" you're seeing. The only hostility I'm
>> seeing is from the OP, which is bizarre considering that he asked for
>> advice and we gave it. What I see is a bunch of people concerned that the
>> OP is teaching novices a bad habit, namely, using assert for error
>> checking. He claims -- angrily and over and over again -- that in his
>> code, the assertions should never fail. Great. Good for him for knowing
>> when to use assert. (...)
>>
>
> But he doesn't.
>
> He asserts:
> assert lo < hi
> but then compares:
> sense =mp(func(hi), func(lo))
>
> sense can't ever be anything other than 1. I actually find it amusing
> that this threat got to 50 posts of raving discussion about assertions
> without anyone spotting that.
>
>
That's because the assert and the comparison are unrelated to each
other. If the function is monotonically decreasing, then by definition
lo<hi would guarantee that func(lo)>= func(hi), which would yield a
sense of 0 or -1.

Trivial example of monotonically decreasing:
def func(inp):
return 53.0 - inp

> Personally, I think the code is an unreadable mess, but that's mostly
> because of all the micro optimizations, not the generality of it.
> Here's my unoptimized, but still equally generic, version:
>
> def _binary_search(lo, hi, func, target, epsilon):
> sense =mp(func(hi), func(lo))
> if sense =0:
> return None
> guess =lo + hi) / 2.
> while abs(func(guess) - target) > epsilon:
> guess =lo + hi) / 2.
> if func(guess) > target:
> hi =uess
> elif func(guess) < target:
> lo =uess
> elif lo =hi:
> return None
> return guess
>
>
And of course your clarified function will fail if the func is
monotonically decreasing.

I still think that rather than using sense in the loop, one should
simply swap lo and hi, and continue.
> This is a newbie course, right? A while True loop might be faster, but
> it's all sorts of wrong for teaching newbies. Likewise, calculating a
> midpoint as mid =hi + lo) * .5 is an aberration in a beginner
> environment. You want your students asking why you're calculating an
> average, not asking why you're multiplying by 0.5. In the same vein, I
> have no words for your target_plus/target_minus cleverness.
>
> The right way to go about it, IMO, is to give them my version, let
> them digest it, make all the necessary changes to it to turn it into
> your (faster) version. Present benchmarks for both, then let the
> readability/performance trade-off sink in. What you achieve with this
> exercise is that, instead of making your students think "I have to
> read that crud!?", they'll respect that ugly code is often the result
> of eking out every last drop of performance from a program as you
> possibly can.
>
>
(untested)

def _binary_search(lo, hi, func, target, epsilon):
""" lo, hi are floats representing the desired range of input values to func()
func() is a function that takes a float argument, and returns a float result
target is the desired result value of func()
epsilon is the allowable error compared to target. If set too small, this function will fail by returning None
precondition: func is monotonic over the range of floating point inputs from lo to hi """
return a float value between lo and hi (inclusive) which yields approximately target
if func(lo) > func(hi):
lo, hi = hi, lo
if not (func(lo) <= target <= func(hi)):
return None #function doesn't have target value within the input range
guess = lo
while abs(func(guess) - target) > epsilon:
guess = (lo + hi) / 2.
if func(guess) > target:
hi = guess
elif func(guess) < target:
lo = guess
elif lo == hi:
return None #function is too steep to have a value within epsilon
return guess

The reason for the "too steep" condition is that with a finite
resolution for 'guess' epsilon could be enough smaller than target as
to make a result impossible. For example, if the slope is 45 degrees,
this happens when epsilon is about 2**51 smaller.


--
http://mail.python.org/mailman/listinfo/python-list


pdpinheiro at gmail

Jul 7, 2009, 12:10 PM

Post #60 of 85 (882 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Jul 7, 8:04 pm, Dave Angel <da...@ieee.org> wrote:
> And of course your clarified function will fail if the func is
> monotonically decreasing.

yeah, I eventually realized that and corrected it... And the assert()/
cmp() confusion too. I blame lack of sleep.

The whole sign/sense thing left a really bad taste in my mouth,
though, and the swapping lo and hi suggestion of yours seems like the
neatest solution presented.
--
http://mail.python.org/mailman/listinfo/python-list


http://phr.cx at NOSPAM

Jul 7, 2009, 6:24 PM

Post #61 of 85 (893 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

pdpi <pdpinheiro [at] gmail> writes:
> while abs(func(guess) - target) > epsilon:
> guess = (lo + hi) / 2.
> if sense * func(guess) > sense * target:
> hi = guess
> elif sense * func(guess) < sense * target:
> lo = guess
> elif lo == hi:
> return None
> return guess

That is completely confusing. I get the, er, impression that "sense"
is supposed to change during the loop, and it takes much head
scratching to tell whether what you have there is right or not. Also,
it calls func 3 times on each loop, which could be extremely slow.
You don't know what func does, so eliminating 2/3 of the calls to it
is not a micro-optimization--it could be a major time saving.

Yet another version:

def _binary_search(x0, x1, func, target, epsilon):
y0,y1 = func(x0), func(x1)
while abs(y1 - target) > epsilon:
if x0 == x1 or cmp(y0,target) == cmp(y1,target):
return None
xn = (x0 + x1) / 2.
yn = func(xn)
if cmp(yn,target) == cmp(y0,target):
x0,y0 = xn,yn
else:
x1,y1 = xn,yn
return x1
--
http://mail.python.org/mailman/listinfo/python-list


gagsl-py2 at yahoo

Jul 7, 2009, 6:30 PM

Post #62 of 85 (883 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

En Tue, 07 Jul 2009 09:51:10 -0300, Jean-Michel Pichavant
<jeanmichel [at] sequans> escribió:
> I've never used sense in that way before, nor I've seen used by others
> until now. However Kj is right, and my dictionary seems wrong
> (wordreference.com). I've searched through others dictionaries and find
> out this is actually applicable to functions. My bad.

Using a common word with its common meaning is important too in order to
understand the code. It's hard enough for students to grasp the algorithm
itself, why make it artificially harder by using strange variable names.

Some years ago I had to endure using an in-house framework with names like
bring_XXX and fix_XXX instead of the usual names get_XXX and set_XXX (that
was C++, emulating properties; I'm not sure of the actual verbs used,
perhaps "obtain" and "establish", but certainly not get/set/put). Add some
undecipherable comments in spanglish, profuse usage of macros that alter
the lexical appearance of the language, and even reading code was a
torture.

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list


pdpinheiro at gmail

Jul 8, 2009, 7:06 AM

Post #63 of 85 (872 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Jul 8, 2:24 am, Paul Rubin <http://phr...@NOSPAM.invalid> wrote:
> pdpi <pdpinhe...@gmail.com> writes:
> >     while abs(func(guess) - target) > epsilon:
> >         guess = (lo + hi) / 2.
> >         if sense * func(guess) > sense * target:
> >             hi = guess
> >         elif sense * func(guess) < sense * target:
> >             lo = guess
> >         elif lo == hi:
> >             return None
> >     return guess
>
> That is completely confusing.  I get the, er, impression that "sense"
> is supposed to change during the loop, and it takes much head
> scratching to tell whether what you have there is right or not.  Also,
> it calls func 3 times on each loop, which could be extremely slow.
> You don't know what func does, so eliminating 2/3 of the calls to it
> is not a micro-optimization--it could be a major time saving.
>
> Yet another version:
>
>     def _binary_search(x0, x1, func, target, epsilon):
>         y0,y1 = func(x0), func(x1)
>         while abs(y1 - target) > epsilon:
>             if x0 == x1 or cmp(y0,target) == cmp(y1,target):
>                 return None
>             xn = (x0 + x1) / 2.
>             yn = func(xn)
>             if cmp(yn,target) == cmp(y0,target):
>                x0,y0 = xn,yn
>             else:
>                x1,y1 = xn,yn
>         return x1

micro-optimization was perhaps too harsh, but it is an optimization
that's not obvious for the newbie, and one best learnt from experience
rather than having it spoon fed. I'll restate: you should start with
the cleanest code possible and mangle it for performance. Then again,
that implicitly assumes that f(x) is more readable than y, which is
really a matter of taste...
--
http://mail.python.org/mailman/listinfo/python-list


digitig at gmail

Jul 8, 2009, 3:25 PM

Post #64 of 85 (870 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

2009/7/7 Steven D'Aprano <steve [at] remove-this-cybersource>:

> Maybe the reason for "so much buggy software" is that people
> inappropriately use assert, thus changing the behaviour of code depending
> on whether it is run with the -O flag or not.

I've done my share of code review and process audits, and assertions
seem *far* to rare for that distinction.

> I don't know what "hostility" you're seeing. The only hostility I'm
> seeing is from the OP, which is bizarre considering that he asked for
> advice and we gave it. What I see is a bunch of people concerned that the
> OP is teaching novices a bad habit, namely, using assert for error
> checking. He claims -- angrily and over and over again -- that in his
> code, the assertions should never fail. Great. Good for him for knowing
> when to use assert. But are the novices going to learn that lesson, or
> will they simply learn "use assert for error checking"?

They are rather more likely to learn if they are taught, aren't they?
Or do you think it's better to keep them in the dark? "There are these
things called assertions -- work them out for yourselves".

I am convinced that the time to teach programmers to consider under
what circumstances a routine can be called and who is responsible for
ensuring that those conditions are met is as soon as they hit the
concept of calling routines. And assertions provide an excellent way
of doing that, fostering good habits for the rest of their careers.
Any hostility from the OP seems to be a response to the persistent
refusal to accept his assurances that he is not using the assertions
for run-time error checking, nor teaching the students to do that,
--
Tim Rowe
--
http://mail.python.org/mailman/listinfo/python-list


no.email at please

Jul 8, 2009, 6:20 PM

Post #65 of 85 (856 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

In <mailman.2671.1246866295.8015.python-list [at] python> Martin Vilcans <martin [at] librador> writes:

>On Fri, Jul 3, 2009 at 4:05 PM, kj<no.email [at] please> wrote:
>> I'm will be teaching a programming class to novices, and I've run
>> into a clear conflict between two of the principles I'd like to
>> teach: code clarity vs. code reuse. =A0I'd love your opinion about
>> it.

>In general, code clarity is more important than reusability.
>Unfortunately, many novice programmers have the opposite impression. I
>have seen too much convoluted code written by beginners who try to
>make the code generic. Writing simple, clear, to-the-point code is
>hard enough as it is, even when not aiming at making it reusable.

>If in the future you see an opportunity to reuse the code, then and
>only then is the time to make it generic.

>YAGNI is a wonderful principle.

Thanks!

kynn

--
http://mail.python.org/mailman/listinfo/python-list


no.email at please

Jul 8, 2009, 6:21 PM

Post #66 of 85 (856 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

In <fMKdnf0dlOXTcMzXnZ2dnUVZ_t2dnZ2d [at] pdx> Scott David Daniels <Scott.Daniels [at] Acm> writes:

>First, a quote which took me a bit to find:
> Thomas William Körner paraphrasing Polya and Svego
> in A Companion to Analysis:
> Recalling that 'once is a trick, twice is a method,
> thrice is a theorem, and four times a theory,' we
> seek to codify this insight.

Good stuff.

>Let us apply this insight:
> Suppose in writing code, we pretty much go with that.
>A method is something you notice, a theorem is a function, and
>a theory is a generalized function.

>Even though we like DRY ("don't repeat yourself") as a maxim, let
>it go the first time and wait until you see the pattern (a possible
>function). I'd go with a function first, a pair of functions, and
>only then look to abstracting the function.

Thanks!

kynn


no.email at please

Jul 8, 2009, 7:19 PM

Post #67 of 85 (859 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

In <mailman.2700.1246895025.8015.python-list [at] python> Tim Rowe <digitig [at] gmail> writes:

>2009/7/4 kj <no.email [at] please>:

>> Precisely. =A0As I've stated elsewhere, this is an internal helper
>> function, to be called only a few times under very well-specified
>> conditions. =A0The assert statements checks that these conditions
>> are as intended. =A0I.e. they are checks against the module writer's
>> programming errors.

>Good for you. I'm convinced that you have used the assertion
>appropriately, and the fact that so many here are unable to see that
>looks to me like a good case for teaching the right use of assertions.
>For what it's worth, I read assertions at the beginning of a procedure
>as part of the specification of the procedure, and I use them there in
>order to document the procedure. An assertion in that position is for
>me a statement to the user of the procedure "it's your responsibility
>to make sure that you never call this procedure in such a way as to
>violate these conditions". They're part of a contract, as somebody
>(maybe you) pointed out.

>As somebody who works in the safety-critical domain, it's refreshing
>to see somebody teaching students to think about the circumstances in
>which a procedure can legitimately be called. The hostility you've
>received to that idea is saddening, and indicative of why there's so
>much buggy software out there.

Thanks for the encouragement.

When I teach programming, the students are scientists. For the
stuff they do, correctness of the code trumps everything else. I
teach them to view assertions as way of translating their assumptions
into code. And by this I mean not only assumptions about the
correctness of their code (the typical scope of assertions), but
also, more broadly, assumptions about the data that they are dealing
with (which often comes from external sources with abysmal quality
control).

My scientific code is jam-packed with assertions. I can't count
the number of times that one such lowly assertion saved me from a
silent but potentially disastrous bug. And yes I find it distressing
that so so few programmers in my line of work use assertions at
all.

kynn
--
http://mail.python.org/mailman/listinfo/python-list


gagsl-py2 at yahoo

Jul 9, 2009, 12:57 AM

Post #68 of 85 (857 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

En Wed, 08 Jul 2009 23:19:25 -0300, kj <no.email [at] please> escribió:

> In <mailman.2700.1246895025.8015.python-list [at] python> Tim Rowe
> <digitig [at] gmail> writes:
>
>> 2009/7/4 kj <no.email [at] please>:
>
>>> Precisely. =A0As I've stated elsewhere, this is an internal helper
>>> function, to be called only a few times under very well-specified
>>> conditions. =A0The assert statements checks that these conditions
>>> are as intended. =A0I.e. they are checks against the module writer's
>>> programming errors.
>
>> Good for you. I'm convinced that you have used the assertion
>> appropriately, and the fact that so many here are unable to see that
>> looks to me like a good case for teaching the right use of assertions.
>> For what it's worth, I read assertions at the beginning of a procedure
>> as part of the specification of the procedure, and I use them there in
>> order to document the procedure. An assertion in that position is for
>> me a statement to the user of the procedure "it's your responsibility
>> to make sure that you never call this procedure in such a way as to
>> violate these conditions". They're part of a contract, as somebody
>> (maybe you) pointed out.
>
>> As somebody who works in the safety-critical domain, it's refreshing
>> to see somebody teaching students to think about the circumstances in
>> which a procedure can legitimately be called. The hostility you've
>> received to that idea is saddening, and indicative of why there's so
>> much buggy software out there.
>
> Thanks for the encouragement.
>
> When I teach programming, the students are scientists. For the
> stuff they do, correctness of the code trumps everything else. I
> teach them to view assertions as way of translating their assumptions
> into code. And by this I mean not only assumptions about the
> correctness of their code (the typical scope of assertions), but
> also, more broadly, assumptions about the data that they are dealing
> with (which often comes from external sources with abysmal quality
> control).

Nobody says you shouldn't check your data. Only that "assert" is not the
right way to do that. Ok, it's easier to write:

assert x>0 and y>0 and x<y

instead of:

if not (x>0 and y>0 and x<y):
raise ValueError, "x=%r y=%r" % (x,y)

but the assert statement is completely ignored if your script is run with
the -O option, and then no check is done.
assert should be used only to verify internal correctness only - to detect
wrong assumptions in the *code* itself. Once you're confident the code is
OK, you may turn off assertions (and improve program speed). But you must
*always* validate input data no matter what - so assert is not the right
tool.

Even worse, never DO anything inside an assertion - it won't be done in
the optimized version. This method becomes almost empty when assertions
are removed (not the intended behavior!):

def process_all(self):
for item in self.items:
assert self.process(item)

> My scientific code is jam-packed with assertions. I can't count
> the number of times that one such lowly assertion saved me from a
> silent but potentially disastrous bug. And yes I find it distressing
> that so so few programmers in my line of work use assertions at
> all.

I'm just saying that some of those assertions probably should be real "if
... raise" statements instead - not that you remove the checks. You may
use this short function, if you prefer:

def fassert(condition, message='', exc_type=AssertionError):
if not condition:
raise exc_type(message)

--
Gabriel Genellina

--
http://mail.python.org/mailman/listinfo/python-list


ethan at stoneleaf

Jul 9, 2009, 1:06 PM

Post #69 of 85 (828 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

kj wrote:
>
> My scientific code is jam-packed with assertions. I can't count
> the number of times that one such lowly assertion saved me from a
> silent but potentially disastrous bug.

Now imagine that asserts had been disabled for that run...

The issue is not "should you validate your inputs", the issue is "do you
want your validation able to be turned off?"

~Ethan~
--
http://mail.python.org/mailman/listinfo/python-list


nobody at nowhere

Jul 9, 2009, 7:28 PM

Post #70 of 85 (824 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Thu, 09 Jul 2009 04:57:15 -0300, Gabriel Genellina wrote:

> Nobody says you shouldn't check your data. Only that "assert" is not the
> right way to do that.

"assert" is not the right way to check your *inputs*. It's a perfectly
reasonable way to check data which "should" be valid, as well as a way to
document what variables are supposed to contain.

--
http://mail.python.org/mailman/listinfo/python-list


steven at REMOVE

Jul 9, 2009, 7:57 PM

Post #71 of 85 (828 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Fri, 10 Jul 2009 03:28:04 +0100, Nobody wrote:

> On Thu, 09 Jul 2009 04:57:15 -0300, Gabriel Genellina wrote:
>
>> Nobody says you shouldn't check your data. Only that "assert" is not
>> the right way to do that.
>
> "assert" is not the right way to check your *inputs*. It's a perfectly
> reasonable way to check data which "should" be valid, as well as a way
> to document what variables are supposed to contain.

Where are those variables coming from?

The distinction really boils down to this:

* asserts should never fail. If there is any chance that an assertion
might fail outside of test suites, then don't use assert.


You can't control what input the caller provides to a function, so unless
the data is generated inside the function, a caller might provide
something unexpected. Therefore, assert is inappropriate for checking
function parameters, even if that function is "private" and only called
by your own functions.

(1) So-called "private" or "internal" functions have a habit of becoming
public, and then you have asserts in public functions.

(2) If public() calls _private(x), and _private uses assert to check the
value of x, there is a risk that if public() is buggy and supplies an
invalid x, the assertion will never be checked and _private() will return
incorrect results.

(3) assert is absolutely unsuitable for enforcing pre-conditions and post-
conditions, unless such conditions are mere "guidelines", because assert
can be switched off at runtime.



It's a fine line to draw. Obviously, if we think something *truly* can
never fail, we don't bother checking it:

def add(x, y):
result = x+y
assert result-y == x
assert result-x == y
return result

is probably overkill for most programs, and yet surprisingly those
assertions will commonly fail for float arguments!




--
Steven
--
http://mail.python.org/mailman/listinfo/python-list


jeanmichel at sequans

Jul 10, 2009, 2:11 AM

Post #72 of 85 (824 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

Nobody wrote:
> On Thu, 09 Jul 2009 04:57:15 -0300, Gabriel Genellina wrote:
>
>
>> Nobody says you shouldn't check your data. Only that "assert" is not the
>> right way to do that.
>>
>
> "assert" is not the right way to check your *inputs*. It's a perfectly
> reasonable way to check data which "should" be valid, as well as a way to
> document what variables are supposed to contain.
>
>
Maybe, one of the assert problem is a semantic issue. Assert is a
convenient way to write in the code "This is a requirement, get lost if
you don't fit in". However it seems we often forget that builtin asserts
can be disabled.
One possible solution for those who prefer to write assertions instead a
'if A then Exception' is to write their own assertion statement and
**raise an exception** that will not be disabled at runtime.

Jea-Michel
--
http://mail.python.org/mailman/listinfo/python-list


digitig at gmail

Jul 10, 2009, 7:38 AM

Post #73 of 85 (830 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

2009/7/9 kj <no.email [at] please>:

> Thanks for the encouragement.

[snip]

> into code.  And by this I mean not only assumptions about the
> correctness of their code (the typical scope of assertions), but
> also, more broadly, assumptions about the data that they are dealing
> with (which often comes from external sources with abysmal quality
> control).

There we diverge. A lot. If "correctness of the code trumps everything
else" (in fact, if it matters at all) and the external data has
"abysmal quality control" then it *must* be checked for correctness
before it is used. If it is not, you have no idea whether your output
is correct or not. And assertions *will* *not* reliably provide that
checking (because they may not be executed). You *must* actively check
the data, using good old-fasioned "if" statements and so on, because
not to do so is to declare that you *don't* care about correctness.
You *know* the input is often wrong, but you're not bothering to check
it?

--
Tim Rowe
--
http://mail.python.org/mailman/listinfo/python-list


charles at declareSub

Jul 10, 2009, 9:27 AM

Post #74 of 85 (828 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Jul 9, 2009, at 10:57 PM, Steven D'Aprano wrote:

> On Fri, 10 Jul 2009 03:28:04 +0100, Nobody wrote:
>
>> On Thu, 09 Jul 2009 04:57:15 -0300, Gabriel Genellina wrote:
>>
>>> Nobody says you shouldn't check your data. Only that "assert" is not
>>> the right way to do that.
>>
>> "assert" is not the right way to check your *inputs*. It's a
>> perfectly
>> reasonable way to check data which "should" be valid, as well as a
>> way
>> to document what variables are supposed to contain.
>
> Where are those variables coming from?
>
> The distinction really boils down to this:
>
> * asserts should never fail. If there is any chance that an assertion
> might fail outside of test suites, then don't use assert.
>
>
> You can't control what input the caller provides to a function, so
> unless
> the data is generated inside the function, a caller might provide
> something unexpected. Therefore, assert is inappropriate for checking
> function parameters, even if that function is "private" and only
> called
> by your own functions.
>
> (1) So-called "private" or "internal" functions have a habit of
> becoming
> public, and then you have asserts in public functions.
>
> (2) If public() calls _private(x), and _private uses assert to check
> the
> value of x, there is a risk that if public() is buggy and supplies an
> invalid x, the assertion will never be checked and _private() will
> return
> incorrect results.
>
> (3) assert is absolutely unsuitable for enforcing pre-conditions and
> post-
> conditions, unless such conditions are mere "guidelines", because
> assert
> can be switched off at runtime.


Unless, of course, you want to switch off such checking at runtime, as
you might when using a design-by-contract approach.

Charles Yeomans
--
http://mail.python.org/mailman/listinfo/python-list


jcd at sdf

Jul 10, 2009, 9:50 AM

Post #75 of 85 (820 views)
Permalink
Re: Clarity vs. code reuse/generality [In reply to]

On Fri, 2009-07-10 at 02:57 +0000, Steven D'Aprano wrote:
> On Fri, 10 Jul 2009 03:28:04 +0100, Nobody wrote:
>
> > On Thu, 09 Jul 2009 04:57:15 -0300, Gabriel Genellina wrote:
> >
> >> Nobody says you shouldn't check your data. Only that "assert" is not
> >> the right way to do that.
> >
> > "assert" is not the right way to check your *inputs*. It's a perfectly
> > reasonable way to check data which "should" be valid, as well as a way
> > to document what variables are supposed to contain.
>
> Where are those variables coming from?
>
> The distinction really boils down to this:
>
> * asserts should never fail. If there is any chance that an assertion
> might fail outside of test suites, then don't use assert.
>

I'm no expert, but the more I read this thread, and the more I think on
it, the more I believe that asserts don't really need to exist outside
of test suites. The function that assertions provide is handled in a
far more robust and maintainable way by unit tests and doctests.
Anything else should be handled by more descriptive exceptions.

The use of assertions in regular code may just be a historical baby step
on the way to real code testing.

To play devils advocate for a moment, one possible use case for assert
statements is if you need to test something that you can't easily get
under a proper unittest or doctest. Maybe you need to know the value of
a variable halfway through a method. A judicious assertion can help
supplement your test suite A better solution would be to refactor so
you can get the needed value under test, but if time constraints won't
allow it, then make your assertion and move on, but only to help you
debug the code, not to protect your code at runtime. Even then, why not
use a proper Exception (unless speed is a major issue)?

Even if it is only used internally in a module, I would still prefer a
ValueError to an AssertionError. It tells you what's happening more
clearly. And it protects you if another caller (even one internal to
the class) calls it with a different set of assumptions.

At minimum, I think there's a heavy burden on an author to justify the
use of AssertionErrors rather than other kinds of Exceptions.

Cheers,
Cliff

--
http://mail.python.org/mailman/listinfo/python-list

First page Previous page 1 2 3 4 Next page Last page  View All Python python RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.