5

I have a lot of classes, realizing some general tasks for different sites :

class AbstractCalculator :
         pass # ... abstract methods lying here

class Realization1 (AbstractCalculator) :

    @classmethod
    def calculate_foo(...) :
        # ...

    @classmethod
    def calculate_bar(...) :
        # ...



class Realization2 (AbstractCalculator) :

    @classmethod
    def calculate_foo(...) :
        # ...

    @classmethod
    def calculate_bar(...) :
        # ...

Then i aggregating all those classes in one dictionary Now i introduce new different API :

class NewAbstractClass :

    # ... introducting new API ...

    @staticmethod
    def adopt(old_class) :
         # .. converting AbstractClass to NewAbstactClass

And then i use adopt() method like @decorator, to convert all old realizations to new.

But it all is very strange and complicated. Is there any better way to do this?

UPD @ColinMcGrath :

No I am asking definitely other.

My adopt() decorator is working, and I have no problems with it functioning (just, its body is not related to my question, so I have not provide it).

I think that hardcoding decoration of several tens of differnet classes right in their source code is not a best idea, and looking for canonical soulution.

uhbif19
  • 3,139
  • 3
  • 26
  • 48
  • Are you looking for a manual solution or a library that does this automatically? – asdf Sep 17 '13 at 19:08
  • @ColinMcGrath I am looking to general design pattern. I know that i have produce somthing very ugly, and looking for best appoach. – uhbif19 Sep 17 '13 at 19:15
  • @ColinMcGrath I know that ZCA's Adapter can do this, for example, but I feel that it can be solved in more convenient way. – uhbif19 Sep 17 '13 at 19:17
  • I found another stack overflow question handling something similar. Does this solve your problem? http://stackoverflow.com/questions/13503079/how-to-create-a-copy-of-a-python-function – asdf Sep 17 '13 at 19:29
  • 1
    "I think that hardcoding decoration of several tens of differnet classes right in their source code is not a best idea" - why is having the source code of your classes a) reflect the actual API, and b) explicitly say what's going on a bad idea? – millimoose Sep 18 '13 at 17:14

1 Answers1

0

In general there is no magic way for code to know that one api equivalent to another.

However, the mechanisms in python for procedural generation of classes are metaclasses and class decorators. You could use a metaclass which uses some information you give it to generate another class. This is a good introduction: http://eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example/

Because of python "duck typing", abstract classes are rarely necessary, and something of a code smell. You should probably just redesign your code such that renaming and abstract classes are unnecessary. In particular, if your code needs to change, it needs to change. I would only do something like this if you are wrapping external code to make several disparate apis compatible.

Something like:

class renamer(type):
     def __init__(cls, classname, bases, dct):
         if '__rename__' in dct:
            dct.update(cls.__rename__)

class orig(object):
      def foo(*params): pass

class newclass:
      __meta__ = renamer
      __rename__ = (('bar', orig.foo),)

Or, you could do a similar thing with a decorator:

def renamer(subs):
    def thedecorator(inclass):
        meta = type(inclass)
        dct = inclass.__dict__.copy()
        dct.update(subs)
        return meta(inclass.__name__,inclass.__bases__,dct)
   return thedecorator

@renamer((('bar', orig.foo),))
class newclass(object): pass
Marcin
  • 48,559
  • 18
  • 128
  • 201