diff options
author | Matti Picus <matti.picus@gmail.com> | 2018-09-17 09:08:42 +0300 |
---|---|---|
committer | Eric Wieser <wieser.eric@gmail.com> | 2018-09-16 23:08:42 -0700 |
commit | 73d7871970a951edd48e5c40bdc7609385ce61e6 (patch) | |
tree | 7e71e96faf55f1d716417c5f057323152d97bbe6 /numpy/core/_internal.py | |
parent | f49c0169f5a62d4bfa62c791e2a4e2b78ddf7517 (diff) | |
download | numpy-73d7871970a951edd48e5c40bdc7609385ce61e6.tar.gz |
MAINT: refactor design of recursive closures (#11910)
Diffstat (limited to 'numpy/core/_internal.py')
-rw-r--r-- | numpy/core/_internal.py | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py index 48ede14d0..9b8f5aef3 100644 --- a/numpy/core/_internal.py +++ b/numpy/core/_internal.py @@ -1,5 +1,5 @@ """ -A place for code to be called from core C-code. +A place for internal code Some things are more easily handled Python. @@ -808,3 +808,35 @@ def _is_from_ctypes(obj): return 'ctypes' in ctype_base.__module__ except Exception: return False + + +class recursive(object): + ''' + A decorator class for recursive nested functions. + Naive recursive nested functions hold a reference to themselves: + + def outer(*args): + def stringify_leaky(arg0, *arg1): + if len(arg1) > 0: + return stringify_leaky(*arg1) # <- HERE + return str(arg0) + stringify_leaky(*args) + + This design pattern creates a reference cycle that is difficult for a + garbage collector to resolve. The decorator class prevents the + cycle by passing the nested function in as an argument `self`: + + def outer(*args): + @recursive + def stringify(self, arg0, *arg1): + if len(arg1) > 0: + return self(*arg1) + return str(arg0) + stringify(*args) + + ''' + def __init__(self, func): + self.func = func + def __call__(self, *args, **kwargs): + return self.func(self, *args, **kwargs) + |