Version imprimable
On est d'accord, depuis le début d'ailleurs et ton premier post résume tout ce que je pense.Citation:
Si c'est vraiment pour faire de l'universel je trouve cela dangereux
Le POO doit être plus précis dans le type d'objet et à la rigueur si c'est un objet connu on pourrait tout simplement en dériver et rajouter des méthodes.
Enfin c'est open bar, on peut rentrer dans des scénarios sans limite de pensée.
Oui, alors quel scénario tu proposes? Entrées? Sorties? Types d'objet? itérable?Citation:
Oui, c'est open code. Pourquoi ne pas jouer avec
;)
Pour ma part, il devrait y avoir un scindage:
- Un proxy:- un foure-tout:Citation:
une petite classe dont le but est d’être utilisée comme proxy de n'importe quoi.
Les proxys etants déjà Built-In, il reste plus qu'à faire le foure-tout.Citation:
ne pas lever d'erreur lorsqu'elle est utilisée à la place de l'objet attendu
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 class PassePartout: """Universal Proxy Object""" _exemple= None __class__ = object def __init__(self, *args, **kw): #s'il passe partout, il doit pouvoir tout gober! self._nextCount = False pass def __getattr__(self,key): if key== "__str__": return "PassePartout" if key== "__repr__": return "PassePartout" return PassePartout() #Dans le fond, c'est plutôt bien pensé def __setattr__(self,key,value): pass def __getitem__(self,key): return PassePartout() #Pareil que plus haut. def __setitem__(self,key,value): pass def __str__(self):return "PassePartout" def __repr__(self):return "PassePartout" def __hash__(self): """same hashcode for every instance""" if PassePartout._exemple is None: PassePartout._exemple= PassePartout() return object.__hash__(PassePartout._exemple) def __call__(self,*args,**kwargs): return PassePartout() def __nonzero__(self,*args,**kwargs): return True def __coerce__(self,other): this= None if other.__class__== float(1.0).__class__: this= 0.0 if other.__class__== int(1).__class__: this= 0 return (this,other) def __len__(self): return 1 len = __len__ def __next__(self): raise StopIteration next = __next__ def __iter__(self): return iter((self,)) def __instancecheck__(self, instance): print "check instance" #je parviens pas à le faire rouler (py2.7) return True def __subclasscheck__(self, subclass): print "check class" #Lui non plus return True
Bonjour afranck64,
Pourquoi
etCode:
1
2 def __len__(self): return 1
Plutôt queCode:
1
2 def __iter__(self): return iter((self,))
Code:
1
2 def __len__(self): return 0
?Code:
1
2 def __iter__(self): return self
@fred1599: Et bien puisque les deux questions qui se sont posées d'elles mêmes sont l'itérable et le fait que l'objet retourné ne correspond pas autant commencer par là, non ?
@+
@PauseKawa vu que l'objet se doit de retourner du "passe-partout" sous 360°.
Avec le __iter__:return self, un list(passe_p) produit une liste vide. (on perd en "passabilité-partout" :aie: )
Bonjour,
Tout d'abord, merci à tous pour vos remarques !
* Désolé pour l'erreur de vocabulaire. Ce n'est pas un proxy de quelque chose, c'est plutôt un "substituable universel" ("Fourre tout" me fait trop penser à un conteneur)
* Le cas d'utilisation qui me semble idéal, ce sont deux classes couplées A et B. Dans mon cas, il s'agissait d'un conteneur B (contenant des A) qui s'organise dynamiquement à chaque fois qu'un des attributs d'un de ses éléments est modifié. Le code étant couplé, il était difficile de créer des A() pour faire des tests sans une instance de B. Pour m'en passer, j'ai fait croire à mes instances de A qu'elles étaient contenues dans un passe partout.
* _ exemple me sert uniquement de hashcode unique. A partir du moment ou l'objet ne contient rien d'intéressant et ne garantit pas la justesse de ce qu'il "renvoie", autant gagner de la mémoire dans les dict ou il apparait.
* Je vous accorde qu'il est plus naturel de renvoyer self, mais j'ai eu besoin de renvoyer une nouvelle instance pour des boucles (infinies sinon) qui testent l'égalité entre un PassePartout et ce qu'une de ses méthode renvoie. Comme j'imagine aisément des codes qui planteraient dans le cas inverse, il faut rendre ce comportement paramétrable. Idem pour l'itération infinie.
* Merci pour les tests d'instance, j'avais oublié.
*Bonne idées, mais je ne suis pas certain, à cause de codes qui itérerait jointement (zip par exemple) sur une liste de passepartout, et une liste de fonctions de ceux ci. Je n'en ai pas eu besoin en tout cas. Eventuellement un autre comportement paramétrableCitation:
vu que l'objet se doit de retourner du "passe-partout" sous 360°.
Avec le __iter__:return self, un list(passe_p) produit une liste vide. (on perd en "passabilité-partout" )
Dans mon cas, B maintient pour chaque (key,value) une liste distincte de ses éléments tels que element[key]== value. Mais on peut imaginer ce qu'on veut : une IHM pour interfacer un objet, un réseau ou on envoie l'information... dans tous les cas, le but est de récupérer des instances de A sans créer un B, qui est en général un objet lourd. Mon approche est de remplacer B par un passepartoutCode:
1
2
3
4
5
6
7
8
9
10
11
12 class A(dict): """ La classe A a besoin d'une instance de B pour fonctionner """ def __init__(conteneur): dict.__init__(self) self.conteneur=conteneur def __setitem__(self,k,v): self.conteneur.notify_change(self,k,v) dict.__setitem__(self,k,v) class B: pass
Et le lien entre A et B ?Citation:
deux classes couplées A et B
Un exemple sur la base du code poster svp ;)
dans cet exemple, aucun autre lien que :
* la classe A a besoin d'un notifiable (appel explicite dans la code)
* Tous les éléments de ce conteneur notifiable doivent coupler __setitem__ et notify(), de sorte que les listes gérées par notify soient tjs à jour.
il s’avère que dans mon cas réel, les instances de A accèdent également à B ailleurs pour d'autres raisons.
Plus généralement, j'ai une classe voiture qui suppose qu'elle possède un moteur et qui lui envoie des ordres (c'est pas ma faute si elle a été mal conçue).
Je veux tester sans moteur le reste de son comportement (elle croit aussi qu'elle a des pneus, etc), et bien je lui installe un moteur passe partout.
Bref, réutiliser du code mal conçu (trop couplé?), en ayant le moins d'accident de voiture possible
Un exemple est déjà plus parlant pour moi, si j'ai bien compris tu souhaiterais un truc de ce genre?
Edit : C'est une relation d'agrégation ou de compositionCode:
1
2
3
4
5
6
7
8
9
10
11 class Moteur(object): def __init__(self): print "Moteur initialise" class Voiture(Moteur): def __init__(self, control_moteur=True): self.control = control_moteur if self.control == True: Moteur.__init__(self) v = Voiture(control_moteur=False)
Ce n'est pas ce que je souhaite, c'est ce que j'ai : je dispose d'un agrégat, mais il n'a pas été prévu pour gérer l'absence de ses composants (il n'y a pas le test if self.control == True: Moteur.__init__(self) ).
Pour découpler ces composants, il faudrait effectivement rajouter ce genre de if. Il faut malheureusement le faire à beaucoup d'endroits, ce qui demande de retoucher le code, donc du temps.
Ce que je souhaite, c'est tester les autres composants de la voiture sans avoir à réécrire son code pour découpler ses composants.
Code:
1
2
3
4
5
6
7
8
9
10
11 class moteur: def __init__(self,voiture): self.voiture= voiture def accelerer(self): self.voiture.roues.tourner() class voiture: def __init__(self): self.moteur= moteur(self) self.roues= roues(self)
avec une boucle for?Citation:
Pour découpler ces composants, il faudrait effectivement rajouter ce genre de if. Il faut malheureusement le faire à beaucoup d'endroits, ce qui demande de retoucher le code, donc du temps.
Ce qui ne fait plus beaucoup de modifications finalement, à moins que je n'ai pas tout compris.Code:
1
2
3 liste_objets = [Moteur, Roues, ...] for objet in liste_objets : objet.__init__(self)
Non, car il faudrait rajouter ce if (qu'il soit dans une boucle ou non) dans toutes les fonctions qui essayent d'utiliser self.moteur. Le problème ne se pose pas uniquement à l'init (par exemple la méthode accélerer dans mon exemple)Citation:
avec une boucle for?
J'avoue être perdu, je ne vois pas la difficulté, sinon peut-être dû à un problème de conception du code dont tu parles, je sais pas?
Sinon le plus simple serait de montrer le code en question afin d'en discuter plus clairement.