Ce n'est pas grave. Ce n'est pas parce que Python autorise à passer outre certains principes (philosophie Python: les programmeurs Pythons sont adultes et consentants) que ces principes n'en sont pas moins bons. En plus quelque chose me dit que ces principes ne sont pas là par hasard et que si tu passes outre, tu le payes tôt ou tard (et plus tu le payes tard plus tu payes )
Comme annoncé hier, concernant l'écriture en comprehension face à l'écriture classique j'ai codé ce petit test
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
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 def fctA(l): return list(x for (x, y) in l if y > 100) def fctB(l): res=list() for (x, y) in l: if y > 100: res.append(x) # Les fonctions à tester fct={ "list" : fctA, "classic" : fctB, } # Initialisation random random.seed() # La liste témoin n=1_000_000 temoin=tuple(zip(random.sample(range(n), n), random.sample(range(n), n))) # Appel des fonctions dans un ordre aléatoire et affichage du chrono print("start", n) for (k, v) in random.sample(fct.items(), len(fct)): t=timeit.Timer(partial(v, temoin)).repeat(repeat=10, number=10) print("%s: min=%f, max=%f, avg=%f" % (k, min(t), max(t), sum(t)/len(t))) # for
Et le résultat
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 llist: min=1.505935, max=1.562826, avg=1.539030 classic: min=1.631876, max=1.742919, avg=1.676472
J'ai découvert ce truc il n'y a pas longtemps (cet été) mais j'en ai mis quasiment de partout.
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Mon but premier, par cette démarche de rajouter des __slots__, n'est pas d'économiser le peu de RAM engendré mais de garantir le respect du principe d'encapsulation.
Le gain de RAM, c'est juste du bonus.
Certes, un développeur voulant profiter du comportement natif pourra tout à fait enlever le __slots__.
Mais alors, je lui poserai la question de pourquoi il le fait.
Mes tutoriels
Avant de poster :
- F1
- FAQ
- Tutoriels
- Guide du développeur Delphi devant un problème
Mes tutoriels
Avant de poster :
- F1
- FAQ
- Tutoriels
- Guide du développeur Delphi devant un problème
Euh... je vois pas trop ce que tu veux dire...
De mon point de vue, le __slots__ rempli parfaitement sa tâche (il interdit tout attribut non explicitement prévu mais les fonctions cachées dans les getters/setters ne sont pas impactées)...
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 class cPoint: __slots__=("__x", "__y") @property def x(self): return self.__x @x.setter def x(self, x): self.__x=x def __init__(self, x=0, y=0): (self.__x, self.__y)=(x, y) # cPoint() a=cPoint(2, 3) print(a.x) a.x=5 print(a.x) a.y=8 # Ici erreur car "y" n'est pas dans le __slots__
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
L'erreur que je faisais, était que je déclarais la propriété directement.
et j'obtenais
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 class Circle: __slots__ = ("ray", ) def __init__(self, ray): self.__ray = ray def __str__(self): return f"Un cercle de {self.__ray} cm de rayon" @property def ray(self): return self.__ray c = Circle(5) print(c)
ValueError: 'ray' in __slots__ conflicts with class variable
En changeant ray par __ray dans le __slots__, je m'attendais à pouvoir écrire dans __ray mais non.
Ce comportement me va, alors je ne fais pas chercher plus loin.
Mes tutoriels
Avant de poster :
- F1
- FAQ
- Tutoriels
- Guide du développeur Delphi devant un problème
Non non, le __slots__ liste juste les attributs que peut posséder la classe, rien de plus, rien de moins
Pour accéder aux attributs privés, on continue à passer par des méthodes éventuellement encapsulée dans des getter/setter, comme avant. Et les méthodes ne sont pas concernées par le __slots__.
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
Et du coup pour terminer le tableau, est-ce qu'il y a un mécanisme similaire pour les méthodes ?
Mes tutoriels
Avant de poster :
- F1
- FAQ
- Tutoriels
- Guide du développeur Delphi devant un problème
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
def c.truc() ?
Non, ça ne me viendrais même pas à l'esprit
Ce que j'entendais par "même mécanisme pour les méthodes", c'est que def __truc() ne soient pas visible en dehors de ma classe.
Pour le dire plus simplement, je cherchais à obtenir des méthodes "protected" et des méthodes "private" (toujours dans l'optique de forcer le respect de l'encaspulation).
De ce que j'ai pu constater d'après mes recherches est que la convention implique que def _truc(self) est considéré comme protected et que def __autre(self) est considéré comme privé mais qu'il n'existe pas (en tout cas je n'ai pas trouvé) de moyen d'interdire l'utilisation de telles méthodes depuis l'extérieur, on compte sur la bonne volonté du consommateur.
Mes tutoriels
Avant de poster :
- F1
- FAQ
- Tutoriels
- Guide du développeur Delphi devant un problème
Ok (on a quitté le monde du __slots__ donc). Pas de souci, c'est le cas. Un attribut ou méthode précédé de deux underscores est invisible du dehors. Je me sers parfois par exemple de méthodes de ce type pour mes traitements internes
Exemple sur un exercice pour créer un objer permettant de gérer une fraction
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 # Objet pour gérer une fraction class cFrac: # Fonction qui calcule le pgcd de deux nombres @staticmethod def __pgcd(x, y): while y: (x, y)=(y, x%y) return x # __pgcd() # Getters/Setters/Deletters num=property(lambda self: self.__num, None, None) den=property(lambda self: self.__den, None, None) # Le constructeur de la fraction def __init__(self, num=0, den=1): if den == 0: raise ValueError("Le dénominateur ne peut pas être à 0 !!!") pgcd=cFrac.__pgcd(num, den) (self.__num, self.__den)=(num // pgcd, den // pgcd) # __init__()
La méthode __pgcd() est privée. Toutefois sa privatisation se fait juste par obfuscation du nom. Son nom est en réalité transformé en _cFrac__pgcd(). Donc privé mais malgré tout accessible si on veut s'en donner la peine (à voir au cas par cas si le jeu en vaut la chandelle).
Exact. Le simple underscore est juste une affaire de convention. Rien n'interdit de l'utiliser depuis le dehors si on le désire sauf qu'il ne faut pas le faire. Et comme je l'ai dit, le double underscore provoque un changement mais un changement connu et donc récupérable. Hé oui, de ce côté là Python reste ouvert (les programmeurs Python sont adultes et consentants). Est-ce une bonne ou une mauvaise chose je ne saurais le dire. Comme pour tout, je pense que la réponse dépend surtout de ce qu'en fait le consommateur. wiztrics a déjà donné beaucoup d'avis intéressants à ce propos dans ses posts. Un de ses arguments c'est que si on veut passer outre bon ok on peut mais si l'objet évolue ensuite tant pis pour toi car en fait tu n'étais pas censé passer outre. Encore une fois les programmeurs Python sont adultes et consentants.
Mon Tutoriel sur la programmation «Python»
Mon Tutoriel sur la programmation «Shell»
Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
Et on poste ses codes entre balises [code] et [/code]
çà n'existe pas avec Python... et je ne vois pas comment on pourrait techniquement faire cela avec un langage interprété.
Python est un langage de programmation pour des adultes consentants...De ce que j'ai pu constater d'après mes recherches est que la convention implique que def _truc(self) est considéré comme protected et que def __autre(self) est considéré comme privé mais qu'il n'existe pas (en tout cas je n'ai pas trouvé) de moyen d'interdire l'utilisation de telles méthodes depuis l'extérieur, on compte sur la bonne volonté du consommateur.
Si vous conduisez une voiture et que vous arrivez devant un feu qui passe au rouge, normalement, vous devez vous arrêter. Mais techniquement rien ne vous interdit d'appuyer sur l'accélérateur!
- W
En commençant par ajouter une expression terminale dans la grammaire. PHP est interprété et sais le gérer via les expression terminales "protected" et "private" de sa grammaire.
Je suis persuadé que l'interpréteur python pourrait le gérer mais que ça impliquerait trop d'incompatibilités pour les innombrables projets existants. Quand on donne beaucoup de liberté, il est compliqué de les retirer. Et en plus ça irait à l'encontre de la philosophie historique de python.
Mes tutoriels
Avant de poster :
- F1
- FAQ
- Tutoriels
- Guide du développeur Delphi devant un problème
On peut y accéder via la ReflexionClass.
Et avec l'introspection, on peut le faire avec Java aussi (mais Java est aussi bien compilé que Python).
Avec Ruby (qui est interprété), on a aussi des private/protected mais on peut passer à travers quand on veut.
A quoi servent des protections qu'on peut violer quand on veut ? Sur que çà coûte à implémenter un truc qui ne sert à rien plutôt que de définir des conventions que chacun s'attache à respecter...
note: les programmeurs sont des adultes consentant vient de G.V.Rossum lui même sur ce sujet.
- W
Il existe des manières de contourner dans beaucoup de langages. Tu en as cité quelques un. Je pourrais également citer le système de réflexion sur les Delphi modernes selon plus ou moins la même implémentation que C#.
Mais c'est là tout ce qui fait toute la différence. Sur tout ces langages, il n'est pas naturel d"aller contre l'encaspulation (le truc qui sert à rien même s'il constituele fondementde la POO). Il faut contourner et cela demande de connaître des fonctionnalités plus avancées. Un débutant n'y parviendra pas facilement.
Alors que pour python, il suffit d'appeler la méthode qui est directement disponible. Il sera très facile pour un débutant, même s'il est adulte et consentant, de se tromper et d'appeler une méthode commençant par un underscore. Tu vas me dire que c'est marqué dans tout les bons tutoriels. Mais pour en avoir parcouru un certain nombre, je peux t'affirmer que beaucoup n'en parlent pas.
Mes tutoriels
Avant de poster :
- F1
- FAQ
- Tutoriels
- Guide du développeur Delphi devant un problème
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager