osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Question regarding the local function object


On 3/15/2019 8:47 AM, Arup Rakshit 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']

To build on Calvin's explanation ...
intersperse other function definitions between the repeated calls

sort_by_last_letter(['ghi', 'def', 'abc'])
def a(): return 'skjsjlskjlsjljs'
print(a)
sort_by_last_letter(['ghi', 'def', 'abc'])
def b(): return 546465465454
print(b)
sort_by_last_letter(['ghi', 'def', 'abc'])

and memory gets reused a different way.

<function sort_by_last_letter.<locals>.last_letter at 0x03A51D40>
<function a at 0x03A51D40>  # <== is same memory as .....^^^^
<function sort_by_last_letter.<locals>.last_letter at 0x043C2710>
<function b at 0x043C2710>  # ditto
<function sort_by_last_letter.<locals>.last_letter at 0x043C2768>

Creating a new list or string did not have the same effect.  I believe 
that CPython function objects must currently all have the same size or 
at least the same max size and conclude that CPython currently allocates 
them from a block of memory that is some multiple of that size.  These 
are, of course, current internal implementation details, subject to 
change and even variation across hardware and OSes.

-- 
Terry Jan Reedy