Bien qu'il peut certainement être fait avec métaclasses, vous pouvez faire ce que vous voulez sans eux parce que dans les classes Python sont eux-mêmes des objets. Les moyens qui, étonnamment, essentiellement rien de plus qu'une traduction presque un-à-un du code C++ est nécessaire. En plus d'être relativement simple à cause de cela, il va également fonctionner sans modification dans les deux Python 2 & 3.
def template(class_T):
"""Factory function to create subclasses of class_T."""
class Foo(class_T):
def fun(self):
print('%s.fun()' % self.__class__.__name__)
Foo.__name__ += '_' + class_T.__name__ # rename the subclass to reflect its heritage
return Foo
class Base1:
def bar(self):
print('Base1.bar()')
class Base2:
def bar(self):
print('Base2.bar()')
Foo_Base1 = template(Base1)
print('Foo_Base1 base classes: {}'.format(Foo_Base1.__bases__))
Foo_Base2 = template(Base2)
print('Foo_Base2 base classes: {}'.format(Foo_Base2.__bases__))
subclass1 = Foo_Base1()
subclass1.fun()
subclass1.bar()
subclass2 = Foo_Base2()
subclass2.fun()
subclass2.bar()
Sortie:
Foo_Base1 base classes: (<class __main__.Base1 at 0x00A79C38>,)
Foo_Base2 base classes: (<class __main__.Base2 at 0x00A79DC0>,)
Foo_Base1.fun()
Base1.bar()
Foo_Base2.fun()
Base2.bar()
Le code dans le (unimaginatively nommé) fonction est template()
un exemple de ce qui est communément appelé un class factory ou une implémentation du modèle d'usine . Par ailleurs, vous pourriez trouver my answer à la question What exactly is a Class Factory? informative.
Edit: Ajout de code pour créer des noms de classe pour chaque sous-classe retournée, qui a été inspiré par @ un aperçu de aaronasterling (dans un commentaire maintenant supprimé) au sujet de la confusion potentielle lors du débogage si la classe fabriqué toujours le même nom .
Impressionnant, je suppose que méta-classes sont trop pour quelque chose de si simple. Cette solution prend tout son sens avec le recul, car les types sont des objets de première classe en Python, et les classes peuvent être créées au moment de l'exécution. Je suppose que je ne suis pas encore assez à l'aise avec la manière dynamique de penser le langage pour arriver à moi tout seul, cependant. – dsimcha
Les modèles * sont des métaclasses en C++, un langage fortement typé. Dans une version faiblement typée comme Python, où les classes sont aussi des objets comme vous l'avez noté, il n'est souvent pas nécessaire d'y aller - mais quand vous le faites, vous n'êtes pas limité aux arguments de template et pouvez faire des choses incroyables. – martineau
** Python est fortement typé **, vous ne pouvez pas ajouter une chaîne et un entier en Python comme vous le feriez dans un langage faiblement typé comme Javascript. Incidemment, ** Python est également dynamiquement-tapé **. –