First, there are a lot of things about this code that are incorrect, or at least weird:
- You have a shared class attribute
__N holding an empty list—but in __init__, you immediately hide that with an instance variable of the same name, presumably holding a number. So, that class attribute is never going to do anything.
- There's also no reason for it to be called
__N. The only reason for double underscores is when you need to protect against superclasses or subclasses accidentally using the same name for something incompatible.
- You're using another shared class attribute
List_class1, but you're initializing it in your __init__. This makes sense for cases like, e.g., registering all instances of a class with the class, but it doesn't make sense for cases where you're trying to create a list per instance. When you construct a dozen class2(10)s, you want each one to have 10 class1 instances, not all of them to share the same 120, right?
- Your
function1 and function2 aren't methods, and can't be called, because they take no self. Or, rather, they do take a self, but under the unusual name params. Which means they end up passing self as the params to every function in class1.
Anyway, it looks like what you're trying to do is create a sort of generic proxy, but one that does a "fan-out" proxy to a list of objects, instead of just proxying to a single object.
So, the same basic techniques for generic proxies will work.
For example, you can do it dynamically with __getattr__:
class class2:
def __init__(self, N):
self.c1s = [class1() for _ in range(N)]
def __getattr__(self, name):
if name.startswith('_'):
raise AttributeError(name)
methods = []
for c1 in self.c1s:
attr = getattr(c1, name)
if callable(attr):
methods.append(attr)
if methods:
def _map(*args, **kw):
return [method(*args, **kw) for method in methods]
return _map
raise AttributeError(name)
class class1:
def function1(self, x, y):
return x+y
def function2(self):
return 'function 2!'
c2 = class2(3)
print(c2.function1(2, 3))
print(c2.function2())
This will print [5, 5, 5] and then ["function 2!", "function 2!", "function 2!"].
Or, since you only want to hold class1 instances, you can do it statically. This has the advantage that class2.function2 will be a real method that you can see in the __dict__, so your interactive interpreter can autocomplete it, etc.
class class2:
def __init__(self, N):
self.c1s = [class1() for _ in range(N)]
for name, value in inspect.getmembers(class1, callable):
if name.startswith('_'):
continue
setattr(class2, name, lambda self, *args, _v=value, **kw: [_v(c1, *args, **kw) for c1 in self.c1s])
OK, that last one could probably be a bit prettier instead of a horrible one-liner, but hopefully you get the idea.