Alternative path for explicit lazy imports

Whilst I see where you’re coming from regarding PEP 810’s use of magical lazy evaluation while generic lazy evaluation is repeatedly rejected for similar magic, I don’t see that the concerns made about the latter really apply to the former.

With generic laziness, every function already in existence could potentially start receiving lazy objects, introducing the potential for inconsistency if the object mutates between being passed to the function and being de-lazified by the function. This also introduced the need to special case lazy objects in isinstance(arg, sometype) and arg is someobject so that arg is evaluated and the expressions don’t incorrectly return false. With PEP 810, in the unlikely event of someone running lazy import numpy and then passing numpy to a function, it just reifies numpy before the function call and we’re back onto normal footing – the function doesn’t know nor need to know that one of its arguments used to be a voodoo lazy object.

Generic laziness also wanted all kinds of ways to (sometimes conditionally) handle a lazy object without evaluating it so that it could cover passing expensive-to-calculate arguments to functions that may not use them. This led to rules that most of us couldn’t follow about when a lazy object really gets evaluated. PEP 810 on the other hand is content with a comparitively simple if you touch it, it’s reified – even at the expense of otherwise possibly being able to support something like def foo(default=lazymodule.something): or class Foo(lazymodule.Base): without upfront reification.

4 Likes