B
Bruno Desthuilliers
Mathias Panzenboeck a écrit :
About the lost weakref problem: in Python, methods are just tiny
wrappers around the object, class and function created at lookup time
(yes, on *each* lookup) (and WWAI, they are by the function object
itself, which implements the descriptor protocol).
Anyway, the whole thing looks quite baroque to me - and I'm known for my
immoderate appetite for brain-melting features....
If I understand correctly, you're doing all this to avoid circular
references while keeping track of a list of methods to call ?
If yes, then you're thru much pain for nothing. Mostly because there are
other much more simpler solutions. The first one is obviously to use
names and getattr. In it's most naïve implementation, this would look like:
class Foo(object):
def __init__(self):
self._methods = set()
self._methods.add('_foo')
def _foo(self):
print "_foo"
def callMethods(self):
for name in self._methods:
meth = getattr(self, name, None)
if callable(meth):
meth()
Now if _methods is supposed to have the same content class-wise (which
is the case in your exemple), no need to have it as an instance method:
class Foo(object):
_methods = set('_foo')
def _foo(self):
print "_foo"
def callMethods(self):
for name in self._methods:
meth = getattr(self, name, None)
if callable(meth):
meth()
We could go further, like using a decorator to mark methods to add to
_methods, and a metaclass to set the whole thing up, but this would
probably be overkill. Unless there are other requirements, I'd
personnaly stop here.
Oh, and yes, while we're at it : Python usually knows how to deal with
circular references....
Yes. KISS.
About the lost weakref problem: in Python, methods are just tiny
wrappers around the object, class and function created at lookup time
(yes, on *each* lookup) (and WWAI, they are by the function object
itself, which implements the descriptor protocol).
When I change the class Wrapper to following, the class Foo works:
class Wrapper(object):
def __init__(self,x):
self.func_name = x.func_name
self.x = weakref.ref(x.im_self)
def __call__(self,*args,**kwargs):
x = self.x()
if x is None:
print "lost reference"
else:
return getattr(x,self.func_name)(*args,**kwargs)
Anyway, the whole thing looks quite baroque to me - and I'm known for my
immoderate appetite for brain-melting features....
If I understand correctly, you're doing all this to avoid circular
references while keeping track of a list of methods to call ?
If yes, then you're thru much pain for nothing. Mostly because there are
other much more simpler solutions. The first one is obviously to use
names and getattr. In it's most naïve implementation, this would look like:
class Foo(object):
def __init__(self):
self._methods = set()
self._methods.add('_foo')
def _foo(self):
print "_foo"
def callMethods(self):
for name in self._methods:
meth = getattr(self, name, None)
if callable(meth):
meth()
Now if _methods is supposed to have the same content class-wise (which
is the case in your exemple), no need to have it as an instance method:
class Foo(object):
_methods = set('_foo')
def _foo(self):
print "_foo"
def callMethods(self):
for name in self._methods:
meth = getattr(self, name, None)
if callable(meth):
meth()
We could go further, like using a decorator to mark methods to add to
_methods, and a metaclass to set the whole thing up, but this would
probably be overkill. Unless there are other requirements, I'd
personnaly stop here.
Oh, and yes, while we're at it : Python usually knows how to deal with
circular references....
But that's ugly.
Indeed.
Any better idea?
Yes. KISS.