1

I have a few dozen classes. Here are two of them:

class Class_A(ClassABC):

    def __init__(self):
        super().__init__()

    def from_B(self, b):
        #do stuff

    def from_C(self, c):
        #do stuff

    #...

    def to_B(self):
        rt = Class_B()
        rt.from_A(self)
        return rt

    def to_C(self):
        rt = Class_C()
        rt.from_A(self)
        return rt

    #...

class Class_B(ClassABC):

    def __init__(self):
        super().__init__()

    def from_A(self, a):
        #do stuff

    def from_C(self, c):
        #do stuff

    def to_A(self):
        rt = Class_A()
        rt.from_B(self)
        return rt

    def to_C(self):
        rt = Class_C()
        rt.from_B(self)
        return rt

    #...

 #class Class_C, Class_D, Class_E, etc,

and here is the ABC:

class ClassABC(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def __init__(self):
        #do stuff

The problem I have is that all the to_* methods in the subclasses follow the same exact pattern, and it becomes tedious to implement them. I would like to automatically generate them in the ClassABC if possible, but so far I have failed. I also tried creating a class decorater for the subclasses, but that didn't work either. I have, however, managed to auto generate the methods in each subclass using exec(), but I rather have the ABC generate them or use class decoraters. Is there a way to do this?

Note: all the classes are in their own separate module

Arlen
  • 6,641
  • 4
  • 29
  • 61
  • maybe renaming `from_A` and `from_B` to something like `from_self` could make it easier. You can have a dict just like `{'A': Class_A, 'B': Class_B}` to help your class decorator... – JBernardo Aug 10 '11 at 02:03
  • @JBernardo No, I don't think that would help. I added more to the example code to be more clear. – Arlen Aug 10 '11 at 02:26
  • Could you give us a better idea what is different between Class_A.from_A and Class_q.from_A? – cwallenpoole Aug 10 '11 at 16:55
  • @cwallenpoole There is no `Class_A.from_A`. `Class_q.from_A` is conversion from `Class_A` to `Class_q`. – Arlen Aug 10 '11 at 20:58
  • Ok, what is different between `Class_A.from_B` and `Class_A.from_C` – cwallenpoole Aug 10 '11 at 21:31
  • @cwallenpoole You may think of it as such: `Class_English.from_French` and `Class_English.from_German`. All the `from_*` methods take an object and modify their internal state based on the type of the input and some other calculations. All the `to_*` methods return new objects. – Arlen Aug 11 '11 at 01:07

1 Answers1

0

First of all, your to_* methods aren't going to work because you need to explicitly include self at the beginning of the argument list to be able to use it in the method body. Secondly, I'd go with something akin to JBernardo's suggestion.

def to_class(self, cls):
    rt = cls()
    rt.from_class(self.__class__)
    return rt

def from_class(self, cls):
    #do stuff, with different things happening based on what class cls is; this may be a good place to use a dict of functions with the class or classname as keys
JAB
  • 20,783
  • 6
  • 71
  • 80
  • sorry, I forgot to include `self` in the `to_*`. Does that change anything? Also, I would like to avoid dictionary for performance reasons. – Arlen Aug 10 '11 at 02:57
  • 1
    You think a dict is slower? It's not, that's how attribute lookup happens anyway. – agf Aug 11 '11 at 05:43
  • @agf Thanks, I'm relatively new to Python, so I thought dict would be slower. – Arlen Aug 20 '11 at 13:21