Reputation: 395
I'm trying to create a class A which is basically a list of objects B. I would like to be able to call a method in A which automatically returns a list of the corresponding method in B:
A.method(x) = [B.method(x) for B in A]
The issue is that I need a dynamical behavior, so any method in B is automatically "inherited" by A without having to hard code it.
I have tried using lambda functions and exec("""def ..."""), but nothing seems to work. Here is an attempt:
class A(object):
def __init__(self,Bs):
self.listOfBs = Bs[:]
if self.listOfBs:
for method_name in dir(self.listOfBs[0]):
if not callable(getattr(self.listOfBs[0],method_name)):
continue
f = lambda x: [getattr(B,method_name)(x) for B in self.listOfBs]
setattr(self,method_name,f)
class B(object):
def __init__(self,name):
self.name = name
def getName(self,x):
return self.name+x
#So if I define:
a = A([B('x'),B('y'),B('z')])
#I would like to have: a.getName('W') = ['xW','yW','zW']
#However I get the error: TypeError: 'str' object is not callable
I think there should be an easy/elegant way of implementing the above behavior in python, but I couldn't find anything that works.
Upvotes: 1
Views: 1369
Reputation: 395
Thanks a lot. I had tried getattr before, but was missing some steps. Just for the record, following Glazner's suggestion here is a working solution, which works both with attributes and methods:
class A(object):
def __init__(self,Bs):
self.listOfBs = Bs[:]
def __getattr__(self, attr):
if not all(hasattr(b,attr) for b in self.listOfBs):
raise AttributeError("Attribute %s not found." %attr)
val = getattr(self.listOfBs[0],attr)
if not callable(val):
return np.array([getattr(b,attr) for b in self.listOfBs])
def call(*args, **kw):
return [getattr(b, attr)(*args, **kw) for b in self.listOfBs]
return call
class B(object):
def __init__(self,name):
self.name = name
def getName(self,x):
return self.name+x
a = A([B('x'),B('y'),B('z')])
a.name #Returns ['x','y','z']
a.getName('W') #Returns ['xW','yW','zW']
Upvotes: 2
Reputation: 8066
You may use __getattr__
to make method lookup dynamic
class A:
def __init__(self, bs):
self.bs = bs
def __getattr__(self, method_name):
def call(*args, **kw):
return [getattr(b, method_name)(*args, **kw) for b in bs]
return call
Upvotes: 3