Question regarding the local function object

Calvin Spealman cspealma at redhat.com
Fri Mar 15 08:54:20 EDT 2019


This is actually part of a not entirely uncommon misconception that can
arise by comparing objects only by their
repr() outputs (the string representation created when you pass them to
print).

You're comparing the ID or memory address of the objects and determining
they must be the same object. In this case,
it is a kind of illusion. The function is being garbage collected at the
end of each call to sort_by_last_letter() and then, on
the next call, that address is reused. It is just common for Python to take
the next available location, and that happens to
be the same because you're re-running generally the same code, so the same
number of objects are created and destroyed
each time.

You can see this by making a slight change: try keeping references to ALL
the created functions and you'll see they all
have different IDs so long as none of them get cleaned up. Try this
slightly modified version:

functions = []
def sort_by_last_letter(strings):
    def last_letter(s):
        return s[-1]
    print(last_letter)
    functions.append(last_letter)
    return sorted(strings, key=last_letter)

Which produces this output:

>>> sort_by_last_letter(['ghi', 'def', 'abc'])
<function sort_by_last_letter.<locals>.last_letter at 0x7f276dd571e0>
['abc', 'def', 'ghi']
>>> sort_by_last_letter(['ghi', 'def', 'abc'])
<function sort_by_last_letter.<locals>.last_letter at 0x7f276dd57268>
['abc', 'def', 'ghi']
>>> sort_by_last_letter(['ghi', 'def', 'abc'])
<function sort_by_last_letter.<locals>.last_letter at 0x7f276dd572f0>
['abc', 'def', 'ghi']

On Fri, Mar 15, 2019 at 8:47 AM Arup Rakshit <ar at zeit.io> wrote:

> Hi,
>
> I am reading a book where it says that:
>
> Just like module-level function definitions, the definition of a local
> function happens at run time when the def keyword is executed.
> Interestingly, this means that each call to sort_by_last_letter results in
> a new definition of the function last_letter. That is, just like any other
> name bound in a function body, last_letter is bound separately to a new
> function each time sort_by_last_letter is called.
>
> If that above is true, why the below program shows the same object
> reference for last_letter every time I call function sort_by_last_letter.
>
> # file name is sample.py
>
> def sort_by_last_letter(strings):
>     def last_letter(s):
>         return s[-1]
>     print(last_letter)
>     return sorted(strings, key=last_letter)
>
> python3 -i sample.py
> >>> sort_by_last_letter(['ghi', 'def', 'abc'])
> <function sort_by_last_letter.<locals>.last_letter at 0x1051e0730>
> ['abc', 'def', 'ghi']
> >>> sort_by_last_letter(['ghi', 'def', 'abc'])
> <function sort_by_last_letter.<locals>.last_letter at 0x1051e0730>
> ['abc', 'def', 'ghi']
> >>> sort_by_last_letter(['ghi', 'def', 'abckl'])
> <function sort_by_last_letter.<locals>.last_letter at 0x1051e0730>
> ['def', 'ghi', 'abckl']
> >>>
>
>
> Thanks,
>
> Arup Rakshit
> ar at zeit.io
>
>
>
> --
> https://mail.python.org/mailman/listinfo/python-list
>


-- 

CALVIN SPEALMAN

SENIOR QUALITY ENGINEER

cspealma at redhat.com  M: +1.336.210.5107
<https://red.ht/sig>
TRIED. TESTED. TRUSTED. <https://redhat.com/trusted>



More information about the Python-list mailing list