* Added a tool to create bound instance method with weak ref to the instance.
This commit is contained in:
@@ -10,10 +10,30 @@
|
||||
import sys
|
||||
import new
|
||||
|
||||
"""
|
||||
wpylib.py module
|
||||
Collection of low-level pythonic hacks
|
||||
|
||||
Instance method hacks
|
||||
---------------------
|
||||
|
||||
make_unbound_instance_method::
|
||||
make_unbound_method::
|
||||
|
||||
One possible reason of using these routines is to provide an
|
||||
alterable calling point with different implementations--somewhat like
|
||||
virtual methods, but something that can be changed dynamically
|
||||
on-the-fly.
|
||||
NOTE: The trick provided by wpylib.py.im_ref.im_ref class is
|
||||
a better way to accomplish the same thing.
|
||||
|
||||
|
||||
"""
|
||||
|
||||
def make_unbound_instance_method(method):
|
||||
"""Generates an unbound instance method from a possibly bound
|
||||
instance method."""
|
||||
instance method.
|
||||
"""
|
||||
return new.instancemethod(method.im_func, None, method.im_class)
|
||||
|
||||
|
||||
@@ -32,6 +52,41 @@ def make_unbound_method(method):
|
||||
return method
|
||||
|
||||
|
||||
def make_weakly_bound_method(method, instance):
|
||||
"""Creates a bound instance method, where the instance is weakly
|
||||
referred.
|
||||
|
||||
This trick is necessary if the bound method is to be attached
|
||||
to that instance's attribute list (e.g. via instance.__dict__),
|
||||
because otherwise a circular reference occurs:
|
||||
|
||||
bound_method -> instance -> bound_method (via __dict__)
|
||||
|
||||
CAVEAT: Know what you are doing! In general, this is a haram trick.
|
||||
We circumvent the standard class type-safety mechanism in python here:
|
||||
if the `method` actually belongs to a completely unrelated class,
|
||||
this routine still accepts it and allow the function to be called.
|
||||
"""
|
||||
# NOTE: This is an identical trick to wpylib.py.im_ref.xbound_im_ref;
|
||||
# the latter (the OO interface) is better because
|
||||
# it does not need function closure, and that the object data is
|
||||
# easier to diagnose.
|
||||
from weakref import ref
|
||||
instance_ref = ref(instance)
|
||||
instance_cls = instance.__class__
|
||||
try:
|
||||
im_func, im_class = method.im_func, method.im_class
|
||||
#im_method = new.instancemethod(im_func, None, instance_cls)
|
||||
except AttributeError:
|
||||
im_func = method
|
||||
# Assume this is a function defined outside a class, which is then
|
||||
# injected into this instance.
|
||||
# The first argument must be the usual `self` argument.
|
||||
return lambda *args, **kwargs: method(instance_ref(), *args, **kwargs)
|
||||
|
||||
return lambda *args, **kwargs: im_func(instance_ref(), *args, **kwargs)
|
||||
|
||||
|
||||
def function_name(f):
|
||||
"""Returns the given name of a function (or callable object)."""
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user