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 <a...@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 > a...@zeit.io > > > > -- > https://mail.python.org/mailman/listinfo/python-list > -- CALVIN SPEALMAN SENIOR QUALITY ENGINEER cspea...@redhat.com M: +1.336.210.5107 <https://red.ht/sig> TRIED. TESTED. TRUSTED. <https://redhat.com/trusted> -- https://mail.python.org/mailman/listinfo/python-list