Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Héritage et manufactures

13 views
Skip to first unread message

Michael Grünewald

unread,
Feb 23, 2012, 5:08:33 PM2/23/12
to
Bonjour,

j'ai encore un petit problème de Python pour lequel j'aimerais beaucoup
obtenir vos recommendations.

J'ai une classe Educator et une manufacture de Educator, qui construit
par exemple des valeurs de Educator à partir du contenu d'un fichier:

class Educator:
def behavior(self):
print "Behave yourself!"

class EducatorReader:
def __init__(filename):

def get(self, i):
"""Get the i-th educator in our file."""
return Educator(…)

Maintenant, je dérive une classe d'Educator, en ajoutant une variable
membre _count_ en surchargeant la méthode _behavior_ pour compter le
nombre de ses appels (dans _count_). J'obtiens une classe

class StatisticalEducator(Educator):


Mon problème est: comment implémenter la manufacture
StatisticalEducatorReader? Idéalement, je voudrais pouvoir utiliser le
procédé suivant:

class StatisticalEducatorReader(EducatorReader):
def get(self, i):
x = EducatorReader.get(self, i)
«add a count field to x»
«promote x to StatisticalReader»
return x

Comment puis-je enlever les guillements dans le pseudo-code précédent?

Une implémentation alternative serait de présenter StatisticalEducator
comme un agrégat contenant un Educator et du matériel de supervision.
L'écriture de la manufacture devient facile mais la maintenance d'un
agrégat est très pénible!

Si quelqu'un avait une solution élégante (en Python, même si les
réponses dans d'autres langages m'intéressent par curiosité) je lui en
serais très reconnaissant!
--
Michael

Laurent Pointal

unread,
Mar 6, 2012, 3:25:31 PM3/6/12
to
A tester:

class StatisticalEducatorReader(EducatorReader):
def get(self, i):
x = EducatorReader.get(self, i)
x.count = 0
x.__class__ = StatisticalEducator
return x

Mais gaffe que ton x n'est pas passé par les phases d'initialisation de
StatisticalEducator...


--
Laurent POINTAL - laurent...@laposte.net
3 allée des Orangers - 91940 Les Ulis - France
Tél. 01 69 29 06 59

Kobayashi

unread,
Mar 10, 2012, 1:03:57 PM3/10/12
to
Je suis peut-être à côté de la plaque ... mais bon :

class Educator:
pass

class EducatorReader:
factory = Educator
def get(self, i):
return self.factory()
pass

er = EducatorReader()
print er.get(0)
<__main__.Educator instance at 0x7ff445ac>

class SatisticalEducator(Educator):
pass

class SatisticalEducatorReader(EducatorReader):
factory = SatisticalEducator
def get(self, i):
x = EducatorReader.get(self, i)
x.count = i
return x
pass

ser = SatisticalEducatorReader()
print ser.get(0)
<__main__.SatisticalEducator instance at 0x7ff4476c>

Michael Grünewald

unread,
Mar 18, 2012, 12:03:58 PM3/18/12
to
Kobayashi wrote:
> Le 23/02/2012 23:08, Michael Grünewald a écrit :
>> Si quelqu'un avait une solution élégante (en Python, même si les
>> réponses dans d'autres langages m'intéressent par curiosité) je lui en
>> serais très reconnaissant!
>
> Je suis peut-être à côté de la plaque ... mais bon :

Pas du tout, c'est exactement la solution que je cherchais! D'ailleurs
je ne vois pas ce qui m'interdisait d'y penser tout seul, ce n'est
pourtant pas bien compliqué. Merci pour ton aide!

Michael

Michael Grünewald

unread,
Mar 18, 2012, 12:52:04 PM3/18/12
to
Laurent Pointal wrote:
> A tester:
>
> class StatisticalEducatorReader(EducatorReader):
> def get(self, i):
> x = EducatorReader.get(self, i)
> x.count = 0
> x.__class__ = StatisticalEducator
> return x
>
> Mais gaffe que ton x n'est pas passé par les phases d'initialisation de
> StatisticalEducator...

Ta réponse marche, et fait exactement ce que j'avais demandé (enlever
les guillemets dans mon pseudo-code), merci!

Cependant, la solution que propose Kobayashi est probablement meilleure,
même si ce n'est pas exactementce que j'avais en tête, car elle permet
d'éviter de dupliquer le code d'initialisationde la classe dérivée. De
plus, elle marche probablement dans beaucoup de langages!
--
Michael

Kobayashi

unread,
Mar 19, 2012, 3:26:44 PM3/19/12
to
Merci,

Si la convention de nommage est figée, on peut se passer
de définir l'attribut factory avec :

class Educator:
pass

class EducatorReader:
def get(self, i):
exec "factory = " + self.__class__.__name__[:-len("Reader")]
return factory()
pass

er = EducatorReader()
print er.get(0)

class SatisticalEducator(Educator):
pass

class SatisticalEducatorReader(EducatorReader):
0 new messages