On Fri, Oct 29, 2021 at 11:22:29AM +0200, Gerrit Holl wrote: > On Fri, 29 Oct 2021 at 11:10, Steven D'Aprano <st...@pearwood.info> wrote: > > Obviously you need a way to indicate that a value in __defaults__ should > > be skipped. Here's just a sketch. Given: > > > > def func(a='alpha', b='beta', @c=expression, d=None) > > > > where only c is late bound, you could have: > > > > __defaults__ = ('alpha', 'beta', None, None) > > __late_defaults__ = (None, None, <code for expression>, None) > > Why not define an object for that?
Because then it would have to be a public, named builtin. Or at least a public, named value, even if it's not in the builtin namespace, it would still be accessible to coders just by introspecting the function object. I think NotImplemented is a good sentinel to use. Its the same size as None, and much less commonly used as a default value. So the algorithm for fitting default values to parameters might look like this pseudocode: # single pass version for parameter in parameters: if parameter is unbound: obj = get default for this parameter, or fail if obj is NotImplemented: obj = get late_bound default for this parameter, or fail if obj is not NotImplemented: obj = (eval obj in function namespace) bind obj to parameter # two pass version, that ensures all early-bound parameters # have a value before the late-bound ones are evaluated for parameter in parameters: if parameter is unbound: obj = get default for this parameter, or fail if obj is NotImplemented: continue bind obj to parameter for parameter in parameters: if parameter is unbound: obj = get late_bound default for this parameter, or fail if obj is not NotImplemented: obj = (eval obj in function namespace) bind obj to parameter > In this example I don't mean a fancy new delayed evaluation type such > as has been discussed elsewhere, but just a sentinel so Python knows > it has to look into __late_defaults__ at all (I'm probably missing > something, and I didn't read all prior emails on this, but why > wouldn't this type contain a reference to the code object directly, > negating the need for __late_defaults__...?). How would the interpreter tell the difference between a code object which is early bound and needs to be returned directly, unexecuted, and a code object which is late-bound and needs to be executed? Any code object inside the function defaults can be grabbed and used as an early default, and we'd want it to remain unevaluated. -- Steve _______________________________________________ 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/TC7JQ6YALXTYWPTTCAECSSLDX47RFGCD/ Code of Conduct: http://python.org/psf/codeofconduct/