[Python] pattern per metaclassi

Matteo Bertini matteo a naufraghi.net
Dom 5 Lug 2009 21:17:23 CEST


Nel flusso del continuo refactoring mi sono scontrato con le metaclassi, 
ma non ho capito bene se mi servono oppure no.
Ho cercato di ridurre ai minimi termini il codice ma di raccontare
comunque la "storia":

class Base(object):
     def __init__(self, deps=None):
         self.deps = deps or []
     def __repr__(self):
         return "<" + self.__class__.__name__ +\
                " deps=" + str(map(repr, self.deps)) + ">"

class Task(Base):
     def __init__(self):
         super(Task, self).__init__()

class SuperTask(Base):
     def __init__(self):
         super(SuperTask, self).__init__([Task()])

print SuperTask()

# <SuperTask deps=['<Task deps=[]>']>

Supponiamo che un giorno Base non basti più ma che ci sia bisogno di 
Base1 e Base2 che operano sulle stesse interfacce con logica diversa. 
Per evitare duplicazioni di codice uso una factory:

class Base1(object):
     def __init__(self, deps=None):
         self.deps = deps or []
     def __repr__(self):
         return "<" + self.__class__.__name__ +\
                " deps=" + str(map(repr, self.deps)) + ">"

class Base2(object):
     def __init__(self, deps=None):
         self.deps = deps or []
     def __repr__(self):
         return "[" + self.__class__.__name__ +\
                " deps=" + str(map(repr, self.deps)) + "]"

def Task(base):
     class Task(base):
         def __init__(self):
             super(Task, self).__init__()
     return Task

def SuperTask(base):
     class SuperTask(base):
         def __init__(self):
             super(SuperTask, self).__init__([Task(base)()])
     return SuperTask

print SuperTask(Base1)()
print SuperTask(Base2)()

# <SuperTask deps=['<Task deps=[]>']>
# [SuperTask deps=['[Task deps=[]]']]

La domanda è, posso usare le metaclassi a livello di modulo per fare una 
cosa del genere:

def MetaBase(base):
     class MetaBase(type):
         def __new__(cls, name, bases, dct):
             return type(name, (base,), dct)
     return MetaBase

__metaclass__ = MetaBase(Base1)

class Task:
     def __init__(self):
         super(Task, self).__init__()

class SuperTask:
     def __init__(self):
         super(SuperTask, self).__init__([Task()])

Dove la metaclasse è un "parametro" del modulo?
Ci sono pattern adatti che non mi vengono in mente o è necessario 
riscrivere tutti gli accessi alle classi come factory(base)?

Seconda domanda, codice che implementi un sistema di plugin che vi è 
rimasto in mente come "bello questo modo di fare le cose!"?

Ciao,
Matteo Bertini



Maggiori informazioni sulla lista Python