[Python-ideas] Delay evaluation of annotations

Steven D'Aprano steve at pearwood.info
Thu Sep 22 22:35:49 EDT 2016


On Thu, Sep 22, 2016 at 09:33:58PM +0000, אלעזר wrote:
> On Fri, Sep 23, 2016 at 12:18 AM Chris Angelico <rosuav at gmail.com> wrote:
> 
> > # Recursion in functions
> > def spam():
> >     return spam()
> >
> 
> I just note that it *is* surprising, for most users, that you can't be sure
> that this is a recursion, yet. 

Who are these "most users" of which you speak? Fortran programmers? C 
programmers? *Beginner* Python programmers? You should specify who you 
are referring about, rather than claim "most" without evidence.

Experienced Python programmers should realise that recursion in Python 
is implemented by name lookup, like all other function calls, so if you 
rebind the name "spam" to something else, the function will call 
something else. This is no different from any other form of function 
call, including calls to built-ins. If you rebind or shadow a name, you 
will change which object is called. That shouldn't be a surprise, 
whether it involves recursion or not.


> So it if you want a trusted-upon recursion
> you should write
> 
> # spam:
> def spam():
>     def spam():
>         return spam()
>     return spam()

*shrug* But if I do that, then I make it difficult or impossible to 
monkey-patch spam on the fly, for instance in the interactive 
interpreter.

I wouldn't do it in production, but for interactive exploritory work, it 
is astonishing how often monkey-patching comes in handy. Just yesterday 
I played around with some code where I monkey-patched the built-in 
iter() so I could get a better idea of how the code worked.

The straight-forward and simple way of writing a recursive spam() 
function surprises beginners, but they might go years or their entire 
career without running into a situation where they are caught by 
surprise. After all, it is rare for productuon code to rename functions, 
and rarer still to do it to recursive functions:

    func = spam
    spam = something_else()
    func()  # why does the recursion not work???

In production code, that sort of thing almost never happens.

On the other hand, your clever trick for preventing that surprise will 
surprise *me* and other experienced Pythonistas who know how recursion 
and function calls work in Python and expect to be able to 
take advantage of that when and if needed.

In other words, in order to protect beginners from accidents which are 
extremely rare, you will take away power from experienced programmers 
who are more likely to want to make use of that power. I don't think 
that's a good tradeoff.

For the avoidance of doubt: we're all adults here. If you personally 
want to write your recursive functions the "trusted" way, go right 
ahead. It will make them just a little bit less useful to experts, add 
an insignificant amount of safety, and require a bit more work on your 
part. But it's your code, and I don't intend to tell you not to do this.

In the meantime, I'll usually just write my recursive functions the 
old-fashioned normal way.



-- 
Steve


More information about the Python-ideas mailing list