Function to avoid a global variable

Chris Angelico rosuav at gmail.com
Fri May 1 19:30:59 EDT 2020


On Sat, May 2, 2020 at 9:14 AM DL Neil via Python-list
<python-list at python.org> wrote:
>
> On 28/04/20 7:36 PM, Chris Angelico wrote:
> >>> "Best"? Not sure about that. Functions are first-class objects in
> >>> Python, so a function *is* a callable object. You don't have to create
> >>> a custom class with a call method just to be able to attach attributes
> >>> to your function.
> >>>
> >>> ChrisA
> >>>
> >>
> >> Using a mutable object as a function default parameter value
> >> and changing it inside the function looks like a "trick"
> >> according to me.
> >
> > Sure. But you're contrasting this to a suggestion to literally just
> > attach attributes to a function. Python lets you actually do that. You
> > don't have to simulate the feature by creating a custom class and
> > making it callable - you just straight-up add attributes to a
> > function. Sure, what you suggested works, but there's no reason to.
>
>
> Functions are objects too! I regularly point-out this powerful facility,
> and its affordances, but...
>
>
> Yes, it's perfectly reasonable and even sensible to attach an attribute;
> BUT do many people expect to find such? If we were to collectively
> survey our own application code, how many examples would we find - as a
> percentage of such a corpus?
>
> Expectation: it would be v.v.low. Accordingly, whilst
> perfectly-implemented Python, and thus not a "trick", at least it is
> something that is easy for 'an ordinary person' to 'miss' (or
> misunderstand).
>

One of the problems with the use of function attributes is that
there's no way to say "this function". You have to use its name.
Otherwise, it would be easy to write self-contained idioms such as
static variables or omitted arg detection without the risk of
polluting the namespace:

def some_function(x, y, z=object()):
    if z is me.__defaults__[0]:
        z = x + y
    ...

def static(**kw):
    def deco(f):
        for name, initial in kw.items():
            setattr(f, name, initial)
        return f
    return deco

@static(called=0)
def other_function():
    me.called += 1
    ...

Obviously the name "me" can't be used, as it'd break a bunch of code,
but conceptually this would be incredibly helpful. It'd also be a
reliable idiom for recursion optimization - any "me()" is guaranteed
to be recursion and may potentially give info to an optimizer.

Perhaps, if Python had a way to identify the current function, it
would feel less odd to attach attributes to it.

ChrisA


More information about the Python-list mailing list