Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object lifetime and inner recursive function #49171

Closed
ocean-city mannequin opened this issue Jan 12, 2009 · 7 comments
Closed

Object lifetime and inner recursive function #49171

ocean-city mannequin opened this issue Jan 12, 2009 · 7 comments
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs)

Comments

@ocean-city
Copy link
Mannequin

ocean-city mannequin commented Jan 12, 2009

BPO 4921
Nosy @pitrou, @ericsnowcurrently, @eric-wieser
Files
  • q112.py
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2009-01-12.12:58:16.096>
    created_at = <Date 2009-01-12.11:19:17.354>
    labels = ['interpreter-core', 'invalid']
    title = 'Object lifetime and inner recursive function'
    updated_at = <Date 2018-09-11.14:43:05.745>
    user = 'https://bugs.python.org/ocean-city'

    bugs.python.org fields:

    activity = <Date 2018-09-11.14:43:05.745>
    actor = 'eric.snow'
    assignee = 'none'
    closed = True
    closed_date = <Date 2009-01-12.12:58:16.096>
    closer = 'ocean-city'
    components = ['Interpreter Core']
    creation = <Date 2009-01-12.11:19:17.354>
    creator = 'ocean-city'
    dependencies = []
    files = ['12704']
    hgrepos = []
    issue_num = 4921
    keywords = []
    message_count = 7.0
    messages = ['79664', '79670', '79672', '79680', '79706', '312343', '324987']
    nosy_count = 4.0
    nosy_names = ['pitrou', 'ocean-city', 'eric.snow', 'Eric.Wieser']
    pr_nums = []
    priority = 'normal'
    resolution = 'not a bug'
    stage = None
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue4921'
    versions = ['Python 2.6', 'Python 3.0', 'Python 3.1', 'Python 2.7']

    @ocean-city
    Copy link
    Mannequin Author

    ocean-city mannequin commented Jan 12, 2009

    Hello. Sorry if this is noise. I expected

    __del__
    out of function
    __del__
    out of function
    __del__
    out of function

    on following code, but actually I got

    out of function
    out of function
    out of function
    __del__
    __del__
    __del__

    Is this expected behavoir? (I believed `a' would be
    freed after returned from f(), so I was suprised)

    If I remove the comment of gc.collect(), the code works as expected.

    ///////////////////////////////

    import gc
    
    class A:
        def __del__(self):
            print("__del__")
    
    def f():
        a = A()
        def g():
            a
            g()
    
    def main():
        for _ in range(3):
            f()
    #       gc.collect()
            print("out of function")
    
    if __name__ == '__main__':
        main()

    @ocean-city ocean-city mannequin added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Jan 12, 2009
    @pitrou
    Copy link
    Member

    pitrou commented Jan 12, 2009

    Since g calls "itself" in its own scope, it is stored as one of its own
    cell vars, which creates a reference cycle. a is also part of its
    reference cycle for the same reason, so it must wait for garbage
    collection to be reclaimed.

    If g didn't keep a reference to its cell vars, closures wouldn't be
    possible, because the cell vars wouldn't survive the end of f's scope.

    (g doesn't have to be recursive, it's enough that it makes a reference
    to itself in its own scope:

    def f():
        a = A()
        def g():
            a
            g

    or even:

    def f():
        a = A()
        def g():
            a
            h
        h = g

    )

    @ocean-city
    Copy link
    Mannequin Author

    ocean-city mannequin commented Jan 12, 2009

    Thank you for explanation. The combination of inner function + method
    variable was very handy for me, but maybe I should refrain from using
    it lightly. :-(

    @ocean-city ocean-city mannequin closed this as completed Jan 12, 2009
    @ocean-city ocean-city mannequin added the invalid label Jan 12, 2009
    @ocean-city
    Copy link
    Mannequin Author

    ocean-city mannequin commented Jan 12, 2009

    A little followup. Attached script q112.py (some puzzle program) ate up
    my RAM (80MB) and never ran GC while solving. Current python GC looks
    at the number of GC objects, but GC object like set object can contain
    many non GC object, so... I feel it would be nice if there is better GC
    triger/timing.

    @pitrou
    Copy link
    Member

    pitrou commented Jan 12, 2009

    Well, tracking memory consumption of each container would be better than
    simpling couting them, but it's much more complicated as well (not to
    mention that memory consumption can vary, so you must recalculate it
    periodically...).

    @eric-wieser
    Copy link
    Mannequin

    eric-wieser mannequin commented Feb 19, 2018

    Would it be possible for function self-reference cell vars to be weak references?

    This wouldn't solve the issue for co-recursive inner functions, but would at least prevent reference cycles for the more common case of simple recursive functions.

    @eric-wieser
    Copy link
    Mannequin

    eric-wieser mannequin commented Sep 11, 2018

    For anyone doing archaeology - this came up on python-dev about a year after this issue was filed: https://mail.python.org/pipermail/python-dev/2009-December/094439.html

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    interpreter-core (Objects, Python, Grammar, and Parser dirs)
    Projects
    None yet
    Development

    No branches or pull requests

    1 participant