Re: [Python-Dev] Example for PEP 343
Phillip writes: > >@do_template > >def with_extra_precision(places=2): > > "Performs nested computation with extra digits of precision." > > decimal.getcontext().prec += 2 > > yield None > > decimal.getcontext().prec -= 2 > > Won't this do the wrong thing if something within the block alters > the precision? Depends on what behavior you want. I wrote it this way partly because that's how the example in the manual was written, and partly because I was thinking "if someone increased the precision by 3 within the block, then we probably want to leave it increased by 3 on block exit". On careful re-consideration, I think it'd be better to require that the block NOT make unbalanced changes to the precision... we could verify it using an assert statement. I avoided caching the context and restoring it, because I WANTED to allow code in the block to make OTHER alterations to the context and not clobber them after the block exits (eg: setting or clearing some trap). It's debatable whether that was a good design choice... there's a great deal of elegence to Guido's version used like this: Guido: > do with_decimal_context() as ctx: > ctx.prec += 2 > # change other settings > # algorithm goes here However, all of these are minor details compared to the bug that Raymond points out: Raymond: > The final "return +s" should be unindented. It should > be at the same level as the "do with_extra_precision()". The purpose of > the "+s" is to force the result to be rounded back to the *original* > precision. In effect, the "with_extra_precision" wrapper causes the calculations to be done with higher precision, AND causes any variables set during the block will retain their higher precision. (It's because context controls OPERATIONS but changing context never affects individual Decimal OBJECTS.) So I fear that the whole with_extra_precision() idea is just likely to tempt people into introducing subtle bugs, and it should probably be scrapped anyhow. Guido's approach to save-and- restore context works fine. -- Michael Chermside (PS: Another reason that I avoided a basic save-and-restore is that we have plenty of examples already of 'do' statements that save-and-restore, I was trying to do something different. It's interesting that what I tried may have turned out to be a poor idea.) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
Guido van Rossum wrote: > Anyway, perhaps we should provide this most general template: > > @do_template > def with_decimal_context(): > oldctx = decimal.getcontext() > newctx = oldctx.copy() > decimal.setcontext(newctx) > yield newctx > decimal.setcontext(oldctx) > > To be used like this: > > do with_decimal_context() as ctx: > ctx.prec += 2 > # change other settings > # algorithm goes here For the 'with' keyword, and the appropriate __enter__/__exit__ methods on decimal Contexts, this can be written: with decimal.getcontext() as ctx: ctx.prec += 2 # change other settings # algorithm goes here # Pre-with context guaranteed to be restored here The decimal.Context methods to make this work: def __enter__(self): current = getcontext() if current is self: self._saved_context = self.copy() else: self._saved_context = current setcontext(self) def __exit___(self, *exc_info): if self._saved_context is None: raise RuntimeError("No context saved") try: setcontext(self._saved_context) finally: self._saved_context = None Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.blogspot.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
On May 17, 2005, at 11:39 PM, Guido van Rossum wrote: > [Raymond Hettinger] > >> However, for a general purpose wrapper, it is preferable to make a >> context copy and then restore the context after the enclosed is run. >> That guards against the enclosed block making any unexpected context >> changes. >> > > (Although if people get in the habit of using the provided wrappers > and the do-statement, there won't be any unexpected changes.) > > >> Also, since the wrapper is intended to work like a try/finally, it >> will >> make sure the context gets restored even if an exception is raised at >> some unexpected point in the middle of the computation. >> > > Yes, that's the point of the do-statement. :- > > Anyway, perhaps we should provide this most general template: > > @do_template > def with_decimal_context(): > oldctx = decimal.getcontext() > newctx = oldctx.copy() > decimal.setcontext(newctx) > yield newctx > decimal.setcontext(oldctx) > > To be used like this: > > do with_decimal_context() as ctx: > ctx.prec += 2 > # change other settings > # algorithm goes here I have yet to use the decimal module much, so I may be completely off here.. but why not write it like this: @do_template def with_decimal_context(): curctx = decimal.getcontext() oldctx = curctx.copy() yield curctx decimal.setcontext(oldctx) Saves a line and a context set :) -bob ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
[Raymond Hettinger] > The sin() example is correct. The precision is changed and restored in > the current context. I got that eventually. :-) > However, for a general purpose wrapper, it is preferable to make a > context copy and then restore the context after the enclosed is run. > That guards against the enclosed block making any unexpected context > changes. (Although if people get in the habit of using the provided wrappers and the do-statement, there won't be any unexpected changes.) > Also, since the wrapper is intended to work like a try/finally, it will > make sure the context gets restored even if an exception is raised at > some unexpected point in the middle of the computation. Yes, that's the point of the do-statement. :- Anyway, perhaps we should provide this most general template: @do_template def with_decimal_context(): oldctx = decimal.getcontext() newctx = oldctx.copy() decimal.setcontext(newctx) yield newctx decimal.setcontext(oldctx) To be used like this: do with_decimal_context() as ctx: ctx.prec += 2 # change other settings # algorithm goes here -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
> I don't see a call to setcontext() in the sin() example in the library > reference. Is that document wrong? I thought that simply modifying the > parameters of the current context would be sufficient. The sin() example is correct. The precision is changed and restored in the current context. However, for a general purpose wrapper, it is preferable to make a context copy and then restore the context after the enclosed is run. That guards against the enclosed block making any unexpected context changes. Also, since the wrapper is intended to work like a try/finally, it will make sure the context gets restored even if an exception is raised at some unexpected point in the middle of the computation. Raymond ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
On May 17, 2005, at 10:36 PM, Guido van Rossum wrote: > On 5/17/05, Raymond Hettinger <[EMAIL PROTECTED]> wrote: > >>> I think you're missing a decimal.setcontext(newcontext) before the >>> yield.. >>> >> >> Right. >> > > I don't see a call to setcontext() in the sin() example in the library > reference. Is that document wrong? I thought that simply modifying the > parameters of the current context would be sufficient. The library reference isn't modifying the parameters in a *copy* of the current context. -bob ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
On 5/17/05, Raymond Hettinger <[EMAIL PROTECTED]> wrote: > > I think you're missing a decimal.setcontext(newcontext) before the > > yield.. > > Right. I don't see a call to setcontext() in the sin() example in the library reference. Is that document wrong? I thought that simply modifying the parameters of the current context would be sufficient. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
> I think you're missing a decimal.setcontext(newcontext) before the > yield.. Right. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
Bob Ippolito wrote: >> One more thought: Rather than just saving the precision, it is >> likely wiser, safer, and more general to just save and restore the >> whole context and let the wrapped block only work with a copy. >> >> oldcontext = decimal.getcontext() >> newcontext = oldcontext.copy() >> newcontext.prec += 2 >> yield None >> decimal.setcontext(oldcontext) >> >> This approach defends against various kinds of unruly behavior by the >> yield target. > > I think you're missing a decimal.setcontext(newcontext) before the > yield.. Seems to me this should be in the standard library ;) Tim Delaney ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
On May 17, 2005, at 9:02 PM, Raymond Hettinger wrote: >>> What's the advantage of using two calls to getcontext() vs. saving >>> > the > >>> context in a local variable? >>> >> >> I also prefer saving the context in a local variable but that is just >> > a > >> micro-optimization. The presentation with multiple calls to >> getcontext() was kept just to match the style of the original -- the >> important change was the absolute save and restore versus the >> original >> relative adjust up and adjust down. >> > > One more thought: Rather than just saving the precision, it is likely > wiser, safer, and more general to just save and restore the whole > context and let the wrapped block only work with a copy. > > oldcontext = decimal.getcontext() > newcontext = oldcontext.copy() > newcontext.prec += 2 > yield None > decimal.setcontext(oldcontext) > > This approach defends against various kinds of unruly behavior by the > yield target. I think you're missing a decimal.setcontext(newcontext) before the yield.. -bob ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
> > What's the advantage of using two calls to getcontext() vs. saving the > > context in a local variable? > > I also prefer saving the context in a local variable but that is just a > micro-optimization. The presentation with multiple calls to > getcontext() was kept just to match the style of the original -- the > important change was the absolute save and restore versus the original > relative adjust up and adjust down. One more thought: Rather than just saving the precision, it is likely wiser, safer, and more general to just save and restore the whole context and let the wrapped block only work with a copy. oldcontext = decimal.getcontext() newcontext = oldcontext.copy() newcontext.prec += 2 yield None decimal.setcontext(oldcontext) This approach defends against various kinds of unruly behavior by the yield target. Raymond Hettinger ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
> What's the advantage of using two calls to getcontext() vs. saving the > context in a local variable? I prefer saving the context in a local variable but that is just a micro-optimization. The presentation with multiple calls to getcontext() was kept just to match the style of the original -- the important change was the absolute save and restore versus the original relative adjust up and adjust down. Raymond ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
What's the advantage of using two calls to getcontext() vs. saving the context in a local variable? On 5/17/05, Raymond Hettinger <[EMAIL PROTECTED]> wrote: > > > > -Original Message- > > From: [EMAIL PROTECTED] [mailto:python-dev- > > [EMAIL PROTECTED] On Behalf Of Phillip J. Eby > > Sent: Tuesday, May 17, 2005 6:06 PM > > To: Michael Chermside; [EMAIL PROTECTED] > > Cc: python-dev@python.org > > Subject: Re: [Python-Dev] Example for PEP 343 > > > > At 02:42 PM 5/17/2005 -0700, Michael Chermside wrote: > > > > ># = SAMPLE #1: increasing precision during a sub-calculation > = > > > > > >import decimal > > > > > >@do_template > > >def with_extra_precision(places=2): > > > "Performs nested computation with extra digits of precision." > > > decimal.getcontext().prec += 2 > > > yield None > > > decimal.getcontext().prec -= 2 > > > > Won't this do the wrong thing if something within the block alters the > > precision? > > Right. > > It should save, alter, and then restore: > >oldprec = decimal.getcontext().prec >decimal.getcontext().prec += 2 >yield None >decimal.getcontext().prec = oldprec > > > Raymond Hettinger > ___ > Python-Dev mailing list > Python-Dev@python.org > http://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > http://mail.python.org/mailman/options/python-dev/guido%40python.org > -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
> -Original Message- > From: [EMAIL PROTECTED] [mailto:python-dev- > [EMAIL PROTECTED] On Behalf Of Phillip J. Eby > Sent: Tuesday, May 17, 2005 6:06 PM > To: Michael Chermside; [EMAIL PROTECTED] > Cc: python-dev@python.org > Subject: Re: [Python-Dev] Example for PEP 343 > > At 02:42 PM 5/17/2005 -0700, Michael Chermside wrote: > > ># = SAMPLE #1: increasing precision during a sub-calculation = > > > >import decimal > > > >@do_template > >def with_extra_precision(places=2): > > "Performs nested computation with extra digits of precision." > > decimal.getcontext().prec += 2 > > yield None > > decimal.getcontext().prec -= 2 > > Won't this do the wrong thing if something within the block alters the > precision? Right. It should save, alter, and then restore: oldprec = decimal.getcontext().prec decimal.getcontext().prec += 2 yield None decimal.getcontext().prec = oldprec Raymond Hettinger ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Example for PEP 343
At 02:42 PM 5/17/2005 -0700, Michael Chermside wrote: ># = SAMPLE #1: increasing precision during a sub-calculation = > >import decimal > >@do_template >def with_extra_precision(places=2): > "Performs nested computation with extra digits of precision." > decimal.getcontext().prec += 2 > yield None > decimal.getcontext().prec -= 2 Won't this do the wrong thing if something within the block alters the precision? ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com