Function to avoid a global variable
DL Neil
PythonList at DancesWithMice.info
Fri May 1 20:50:11 EDT 2020
On 2/05/20 11:30 AM, Chris Angelico wrote:
> 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.
The trouble is, functions seem to have an existential crisis: they know
their own __name__ but have no sense of self! However, all is not lost
because they are still very __func__-y.
(apologies to anyone reading this whilst drinking)
Unfortunately, Shakespeare is not the only one to ask: what's in a name,
Rosie?
>>> def double( x ):
... return x + x
...
>>> double( 2 )
4
>>> double.__name__
'double'
### so-far, so-good - but let's pick-up the pace:
>>> pasodoble = double
>>> pasodoble( 2 )
4
>>> pasodoble.__name__
'double'
### You're so tired (from working quickly, perhaps) that you can't even
remember your own __name__?
(by extrapolation, I estimate; but you (@Chris) will no doubt, educate)
I'm assuming this has something to do with "decorators"?
In relation to the wider part of the problem-mentioned, a class is
instantiated to become a second, and separate-but-linked, object.
Whereas the two function-names are merely multiple labels to the same
object (and id()):
>>> pasodoble
<function double at 0x7f57b5873a70>
>>> double
<function double at 0x7f57b5873a70>
### Whereas:-
>>> class C():
... '''Docstring that says nothing about a class that does just as
much.'''
...
>>> c = C()
>>> C.__name__
'C'
>>> c.__name__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute '__name__'
### Wait a minute! Have you forgotten your own name?
### What else don't you know?
>>> c.self
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'self'
>>> c.__doc__
'Docstring that says nothing about a class that does nothing.'
### (yes, I know, *I* caused the first of these two!)
### However, they are separate entities. Proof:
>>> id( C )
94619010560432
>>> id(c)
140014684436880
Hence, being empowered to accomplish a lot more with instantiated classes.
Although methods are merely functions, a method enjoys 'extra' by virtue
of being an attribute of a class's instance and being able to call-upon
further attributes within the same namespace.
--
Regards =dn
More information about the Python-list
mailing list