On Fri, Dec 10, 2021 at 7:54 PM Eric V. Smith <e...@trueblade.com> wrote:
> Not sure if you meant this to go to the list or not. > I did — ( I know it seems to be the consensus, but I really think respond to list should be the default…) Moving on… On 12/10/2021 7:50 PM, Christopher Barker wrote: > > Thanks Eric, this is a great example, thanks. > > It does raise some questions. Though. > > If we could use any expression as a deferred expression, then we still > have the two key questions: > > When does it get evaluated, and what namespaces does it use? > > I agree those are good questions. I think, like PEP 671, it would get > evaluated at the start of the function (in this case, __init__). It's > easier for dataclasses, because I could just force the evaluation there. > But for normal function arguments, maybe we'd have to say that before the > function starts executing, any arguments which are deferred objects > automatically are evaluated. And I think the namespace would be where it's > defined. > Ahh, then that would make them less useful for default parameters— even for the dataclass case. It would work fine if you used only builtins (or literals) but that’s about it. So Chris’ canonical example of n => len(input_list) wouldn’t work. Which is why I think that if there were a general purpose deferred object, we’d need special syntax or rules for when used as late-bound defaults. I'll admit I haven't thought all of this through in enough detail to > implement it. I'm just trying to point out that we could use the general > concept in other places. > Which is exactly what I asked for — thanks! I think this is a really interesting use case, not so much as it’s a general purpose deferred object, but because it’s about how to do/use late-bound defaults in meta programming. > def fun(n): > return `len(n)` > > @dataclasses.dataclass > class A: > length: n = fun() > > What would that put in the signature? What namespace would the express e > evaluated in? > > I think it should be evaluated in the context of "fun". Clearly it would > need to create a closure. > Which would be a potentially useful deferred object, but not a good one for late-bound defaults. Here’s a new (not well thought out) idea: @dataclasses.dataclass class A: Input_list: list length: int => len(input_list) So length gets set to a “late bound default expression” that Is an actual value. It would have to store the expression itself, probably as a string, and it would get evaluated in the namespace of the function, when the function was called. So the generated __init__ would be the same as: def __init__(self, input_list, length=>len(input_list): And you could also do: get_length => len(input_list) @dataclasses.dataclass class A: Input_list: list length: int = get_length Not that that would be a good idea. This suggestion would mean that “=>” would create a deferred expression, but it would not be a general purpose one. Though maybe there could be a way to evaluate it in a more general way, kind of like eval — where you can control the namespaces used. I guess what I’m suggesting is that we could create a very specific kind of deferred object, and in the future expand it to more general use. Rather than the general case rendering the late-bound default concept. -CHB > -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
_______________________________________________ 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/7PYISXVUZMK2A7VUPNYU4Q2QD6JJEEUC/ Code of Conduct: http://python.org/psf/codeofconduct/