Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Jouter des méthodes à une classe d'un module (perso)

13 réponses
Avatar
moky
Bonjour à toutes et à tous


J'ai un certain nombre de scripts qui me servent à manipuler des fichiers.

J'ai donc créé un module qui définit les classes le plus utiles. Mais
pour certaines applications, j'ai besoin de leur ajouter des méthodes en
plus.
Je peux faire hériter (voir l'exemple plus bas), mais je me heurte à un
problème : certaines fonctions et méthodes de mon module retournent des
instances des classes de mon module. Et pour elles, je ne peux pas
utiliser les méthodes supplémentaires.


Mettons que ClasseFoo soit une classe dans le module ModuleFoo, et que
la fonction FonctionFoo retourne une instance de ClasseFoo.

Dans mon programme principal je voudrais être capable de
1. Ajouter une méthode MethodePlus à la classe ClasseFoo (héritage, ok)
2. Utiliser la méthode MethodePlus sur les objets créés par FonctionFoo.
(pas ok parce que FonctionFoo retourne un objet qui ne profite pas de
l'héritage)




Par exemple, la classe Repertoire dans mon module perso manip


-------------- Extrait de manip.py ----------------

class Repertoire (object):
def __init__ (self,nom):
self.chemin = nom
self.existe = os.path.isdir(self.chemin)

-------------- fin de l'extrait ----------------

Maintenant, dans certains scripts utilisant cette classe, j'ai besoin
d'une ou deux méthodes très spécifiques supplémentaires.

Mettons que dans mon programme principal j'aie besoin d'une classe qui
contient exactement les méthodes de Repertoire, mais avec une méthode
"essai" en plus. Je fais ceci :

# manip est le nom du module
class Repertoire(manip.Repertoire):
def __init__(self,nom):
manip.Repertoire.__init__(self,nom)
def essai(self):
return "ici "+self.chemin


Faire
x = Repertoire("blable")
print x.code()
produit effectivement la sortie
ici blabla


Jusque là, ça va.
Maintenant le problème est que mon module a une fonction qui retourne un
objet de la classe Repertoire, par exemple


----------- Encore dans le module ---------
def Home(utilisateur):
return Repertoire("/home/"+utilisateur)
----------- Fin de l'extrait ---------


Dans mon programme principal, maintenant je fais

x = Home("moi") # tout se passe bien
print x.chemin # L'héritage fait correctement afficher /home/moi
print x.code

La dernière ligne ne fonctionne plus parce que x est une instance de la
classe Repertoire du module, et non de mon programme principal.



Comment faire pour ajouter des méthodes ? Repenser mon module/programme
autrement ?
Je n'ai pas très envie de mettre toutes les méthodes dans le module,
parce qu'alors, pour peu que je sois en train de travailler sur une
méthode qui plante pour un script, plus aucun des scipts utilisant le
module ne fonctionne.

Merci pour vos lumières
Bonne aprème
Laurent

3 réponses

1 2
Avatar
moky
>> ah ah ! C'est ce que je me retenais de faire parce que j'avais dans
l'idée, justement, qu'il était mieux de tout mettre dans les classes.



Encore une victime de la pensée unique !-)



N'empèche que tout mettre dans les classes crée une homogénisation des
notations; c'est la principale motivation que j'ai à tout vouloir mettre
dans les classes.

Quand j'ai un objet x de la classe Repêrtoire, et que je veux en
extraire une action ou une information, je dois parfois faire

x.methode(args)
et parfois
fonction(x,args)

Mais si j'ai bien compris ce qui a été dit plus haut, l'un n'est qu'un
sucre syntaxique pour l'autre.


J'aurais alors aimé que l'exemple suivant fonctionne:

-------------------------------------------
# La classe Repertoire est définie dans manip.py et a une méthode
# chemin.
def codeRepertoire(self):
return self.chemin

x = manip.Repertoire(HOME+"/essai")
print codeRepertoire(x)
print x.codeRepertoire()

------------------------------------------

Le premier print fonctionne, mais évidement pas le second, sans surprise :
AttributeError: 'Repertoire' object has no attribute 'codeRepertoire'


Bonne aprème
Laurent
Avatar
Bruno Desthuilliers
moky a écrit :

ah ah ! C'est ce que je me retenais de faire parce que j'avais dans
l'idée, justement, qu'il était mieux de tout mettre dans les classes.



Encore une victime de la pensée unique !-)



N'empèche que tout mettre dans les classes crée une homogénisation des
notations; c'est la principale motivation que j'ai à tout vouloir mettre
dans les classes.



Tu risques d'être malheureux avec Python, alors. Un bon nombre de
fonctionnalités sont implémentées en tant que fonctions génériques (ie:
len, sorted, reversed, enumerate, etc....), et même l'instanciation
d'une classe utilise une syntaxe d'appel de fonction (et est e fait
implémentée de la même façon, les classes et les fonctions étant tout
simplement des objets 'appelables', c'est à dire implémentant
l'opérateur d'appel (__call__)).

Python est 100% objet, dans le sens où tout est un objet. Mais ce n'est
pas un langage "pur" objet - il mixe allègrement procédural, objet et
fonctionnel. Avec pour philosophie que tous les problèmes n'appellent
pas la même solution.

Quand j'ai un objet x de la classe Repêrtoire, et que je veux en
extraire une action ou une information, je dois parfois faire

x.methode(args)
et parfois
fonction(x,args)

Mais si j'ai bien compris ce qui a été dit plus haut, l'un n'est qu'un
sucre syntaxique pour l'autre.



Tout à fait. Mais s'il a un intérêt (le polymorphisme - enfin, _une_
forme de polymorphisme), ce sucre a aussi un coût (les opérations
supplémentaires nécessaires à la résolution de l'attribut, la
construction d'un objet méthode etc).


J'aurais alors aimé que l'exemple suivant fonctionne:

-------------------------------------------
# La classe Repertoire est définie dans manip.py et a une méthode
# chemin.
def codeRepertoire(self):
return self.chemin

x = manip.Repertoire(HOME+"/essai")



<hs>
puis-je te conseiller os.path.join ?
</hs>

print codeRepertoire(x)
print x.codeRepertoire()



Il n'y a rien de magique dans la façon dont une fonction attribut d'une
classe devient une méthode d'instance. C'est même assez bien documenté
(et je l'ai moi-même expliqué en détail plusieurs fois sur c.l.py, et
probablement au moins une fois ici même).

Par contre, ce que tu demandes là non seulement nécessiterait une forme
de magie, mais en plus serait probablement assez difficile à formaliser
proprement et de façon non ambigüe.

Bonne nouvelle: tu sais maintenant comment faire (de façon explicite)
pour obtenir ce résultat. Accessoirement, si tu veux ajouter la méthode
'codeRepertoire' à une seule instance (et non à toute la classe):

x.codeRepertoire = codeRepertoire.__get__(x, type(x))

Ce que je voulais dire, c'est que selon le cas d'utilisation, ce genre
de manip est soit la bonne chose à faire, soit une complefixication
arbitraire et inutile.
Avatar
OdarR
On 25 mar, 09:44, Bruno Desthuilliers <bruno.
wrote:
OdarR a écrit :
> les functions se trimballent comme des objets :-)

Ce qui est normal, vu que ce *sont* des objets.



Oui, oui, et c'est génial :-)

Olivier
1 2