On Thu, 7 Apr 2022 at 02:17, Christopher Barker <python...@gmail.com> wrote: > > On Wed, Apr 6, 2022 at 5:11 AM Oscar Benjamin <oscar.j.benja...@gmail.com> > wrote: >> > I'd be curious to know what alternatives you see. When a user writes `x + >> > y` with both `x` and `y` instances of `decimal.Decimal`, the decimal >> > module needs to know what precision to compute the result to >> (as well as what rounding mode to use, etc.). Absent a thread-local context >> or task-local context, where would that precision information come from? > > Why is that absent? -- it seems a task local and/or thread local context is > exactly what should be done.
https://docs.python.org/3/library/decimal.html#decimal.localcontext The Decimal module has a global default context, and per-thread contexts which can be set permanently or with a context manager. It never offers per-module or per-function or any other scope of configuration; at any given moment, there is precisely one context for code running in any particular thread. >> One possibility is to attach the context information to the instances >> so it's like: > > That seems the obvious thing to me -- a lot more like we already have with > mixing integers and floats, and/or mixing different precision floats in other > languages (and numpy). Not so obvious to me, as it would require inordinate amounts of fiddling around when you want to dynamically adjust your precision. You'd have to reassign every Decimal instance to have the new settings. Also: what happens when there's a conflict? Which one wins? Let's say you do "a + b" where the two were created with different contexts - do you use the lower precision? the higher precision? What about rounding settings? Do you need a meta-config that explains how to resolve conflicts between configs? Where would that be stored? Maybe the current way seems more obvious to me since I come from a background of working in REXX, which also had global configuration of these sorts of things (eg "NUMERIC DIGITS 1234" to set the precision, "NUMERIC FUZZ 2" to make numbers compare equal if close). It just seems like the simplest and most convenient way to do things. > Perhaps even something as simple as "Preserve the precision of the highest > precision operand" would go a long way. And some people will loudly dispute that, wanting to avoid false precision. "Adopt the precision of the lowest precision operand" is, for many purposes, much more sane. You'll never satisfy everyone. >> Realistically do many users want to use many different contexts and >> regularly switch between them? I expect the common use case is wanting >> to do everything in a particular context that just isn't the default >> one. > > > I don't know that that's true in the least -- sure, for a basic script, > absolutely, but PYthon has become a large ecosystem of third party packages > -- people make a LOT of large systems involving many complex third party > packages -- the builder of the system may not even know a package is using > Decimals -- let alone two different third party packages using them in very > different ways -- it's literally impossible for the developer of package A to > know how package B works or that someone might be using both. > Indeed. But I don't hear people complaining that they need to have per-module Decimal contexts, possibly since it's never actually a module-by-module consideration. The one thing that threaded contexts don't handle is asyncio, and I haven't checked this, but I believe that "with Decimal.localcontext() as ctx:" uses an asyncio-aware definition of "thread-local" that actually allows multiple tasks to have independent contexts. That would mean that this sort of thing will work sanely: async def task1(): with Decimal.localcontext() as ctx: ctx.prec = 100 await something() a = b + c async def task2(): with Decimal.localcontext() as ctx: ctx.prec = 4 await somethingelse() a = b + c and regardless of exactly what each task does, there's a guarantee that code executed inside the 'with' blocks has the appropriate context. And that's true even if parts of it are imported from other modules. I've never used asyncio + Decimal.localcontext, so I can't say further on that. > Then put all this behind a multithreading web server, and you have a recipe > for chaos. > That's handled, since Decimal contexts are set on a per-thread basis. ChrisA _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/UI5ZN7ED4JZKXUDDTLAPOEXU5YZXZ7WA/ Code of Conduct: http://python.org/psf/codeofconduct/