Salut,
Rien de bien mirobolant, juste une appli python qui permet de créer des fichiers .desktop pour Linux (Ubuntu).
Le git est là :
https://github.com/diablo76600/Ubuntu-Desktop-File
Salut,
Rien de bien mirobolant, juste une appli python qui permet de créer des fichiers .desktop pour Linux (Ubuntu).
Le git est là :
https://github.com/diablo76600/Ubuntu-Desktop-File
bonjour
coté "linux":
Pourquoi cette liste de catégorie pas standard ?
La liste officielle est ici et à noter que TextEditor n'est qu'une des nombreuses sous-catégories.
Pourquoi parler de ubuntu ?
Ces fichiers sont un standard freedesktop respecté par les bureaux.
Pourquoi écrire un outil en QT alors que ubuntu est gtk (normalement) ? Pour kde ok, mais pour gnome (comme son nom et l'icône l'indique), cela me parait absurde. Mais, ok si c'est pour tout bureau
Choix de l'icône :
Avoir la possibilité de piocher dans le thème actif me semble un minimum !
Lanceur de cette application:
Pourquoi créer un script bash alors qu'il suffit de mettre un shebang à ton fichier main.py ?
--------------
Coté python je n'ai pas regardé en profondeur, juste très surpris de trouver un fichier "model.py" sans le "modèle" des datas de ce fichier.
En fait, tu n'utilises même pas un modèleDu coup, le métier est complètement imbriqué dans la Gui et ce qui entraine que je n'ai même pas envie de lire le code.
Dans le dialogue de sauvegarde, tu pourrais ajouter filter = "Application file (*.desktop)"
Bonjour
Une critique (un conseil): par exemple sur cette fonction (au hasard)...
... pourquoi définir le type de façon textuelle ? C'est tout sauf efficace. Analyser une chaine c'est loooong (relativement aux comparaisons numériques je veux dire). Surtout qu'en plus Qt offre déjà les constantes existantes !!! Pourquoi en redéfinir d'autres qui seront au mieux inutiles ?
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 def display_message(title: str, text: str, type_message: str) -> None: """Display a message box with the specified title, text, and type.""" if type_message == "warning": QMessageBox.warning(None, title, text) else: QMessageBox.information(None, title, text)
Et à l'appel, tu lui passes au choix QMessageBox.Warning ou QMessageBox.Information. Ou (à voir) un autre flag permettant d'afficher un autre type de messageBox (fonction alors à faire évoluer ce qui est assez facile dans la structure match...)
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 def display_message(title: str, text: str, type_message=QMessageBox.Information: int) -> None: """Display a message box with the specified title, text, and type.""" match type_message: case QMessageBox.Warning: box=QMessageBox.warning case QMessageBox.Information: box=QMessageBox.information # match box(None, title, text)
Autre chose: hériter de Qt c'est bien... mais cela ne doit pas faire perdre les avantages des objets d'origine (autrement dit, on préserve les objets et tous leurs paramètres). Surtout...
...que ce n'est franchement pas super compliqué...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 class UbuntuDesktopFileCategoriesView(QDialog): """Manage the Ubuntu Desktop File Categories View.""" def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs)
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]
Il ne faut pas exagérer !Analyser une chaine c'est loooongL'application ne va certainement pas afficher 1000 erreurs en même temps.
mais: je suis tout a fait raccord avec la modification !
@Diablo76
En programmation, il est classique de remplacer les constantes chaines (dupliquées) par des constantes numériques :
- moins de place en mémoire
- plus rapide ...
- surtout pas de risque d'erreur (en gros, tu as presque écrit : getattr(QMessageBox, type_message)(None, title, text))
ps: voir, parfois, si besoin, remplacer par des constantes de type enum
Le "côté obscur" n'est pas plus fort, mais il requiert une discipline et une vision à long terme pour résister à ses tentations.
Les bénéfices d'une architecture propre et d'une conception réfléchie surpassent largement les facilités de développement à court terme.
Le "côté obscur" (opter pour la facilité et la rapidité à court terme) peut sembler attrayant, mais il conduit souvent à une dette technique accrue et à des difficultés lorsqu'il s'agit d'adapter ou d'étendre l'application.
Note sur les model Qt : ce ne sont que des interfaces entre un widget et des datas ! Nous pouvons donc avoir des datas indépendantes de l'interface et suivre facilement le paradigme de fred1599 (à cette étape)
ps: ne pas chercher ici une logique métier ou pythonnesque à la classe Métier
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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 @dataclass class Person: nom: str age: int class Metier: def __init__(self): self._datas = {} def retourne(self, index): return self._datas[index] def change(self, index, person): if person.age < 18: raise Exception("règle métier") self._datas[index] = person def count(self): return len(self._datas) class personnes_model(QtCore.QAbstractListModel, database_connecteur="'il vient de la gui ? non"): def __init__(self, parent=None): super().__init__(parent) self._datas = Metier(database_connecteur) def rowCount(self, parent=QtCore.QModelIndex()): return self._datas.count() def data(self, index, role): if role == QtCore.Qt.DisplayRole: return self._datas.retourne(index.row()).nom if role == QtCore.Qt.UserRole + 666: # vouloir l'objet dans la GUI ? c'est le diable (si il est mutable) return self._datas.retourne(index.row()) def addRow(self, name, age): self._datas.ajout(Person(name, age)) def removeRow(self, index): pass![]()
Je n'ai fais qu'un projet professionnel en PyQt, autant dire que je ne suis pas expérimenté avec... Je ne vais pas avoir une critique sur l'utilisation de Qt !
Une de mes erreurs (en ce qui me concerne, car l'entreprise ne voit pas le mal) avaient été de rendre ce projet totalement dépendant de PyQt.
Imaginons, que je veuille passer de PyQt à wxPython ou à Kivy ? Est-ce que tout mon code est bon à mettre à la poubelle ? Sur mon projet, oui !
C'est pour cela que maintenant dans tous mes projets je fais une fixette sur l'architecture du projet, c'est pour moi un temps que je ne négocie jamais avec mes chefs... L'objectif est de permettre d'ajouter du code, et de ne jamais en supprimer (évolution permanente).
Si ça vous intéresse, je vous propose de lire ce blog qui parle de la "clean architecture" d'Uncle Bob, tout est indépendant (si je veux passer de SQL à NoSQL par ex., ça doit être possible sans rien supprimer de l'existant SQL) !
J'ai bien évidemment le bouquin qui est je dois dire complexe à lire (pas parce-qu'il est en anglais, mais un peu vaste, on s'attend à plus de précision).
C'est très appréciable de se dire que ses projets persistent dans le temps, et à vrai dire aux nombres importants de projets que j'ai pu lire, très rarement je rencontre ce type d'architecture (rencontré 1x dans ma carrière).
Et perso, comme Sve@r, l'IHM n'est que Vue ! Mais cela implique de nombreux découpage de modules, une organisation plus complexe au départ, mais avec de nombreux avantages par la suite, comme par exemple la simplification des tests unitaires, une évolution rapide du projet, etc.
Et hélas c'est le cas de beaucoup. Parce qu'entre écrire directement son select truc from machin dans le widget Qt qui va afficher les datas ou créer la classe modele.select qui va se charger de récupérer les datas en cohérence avec le vrai MVC les sirènes de la tentation et de la facilité font malheureusement que...
Certes dans mes projets mes tables sont toutes gérées par un objet dédié qui contient les méthodes "update" et "delete" mais pour le select... Je pense que le vrai et pur MVC, celui qui permet de changer facilement et immédiatement X par Y est une utopie.
- est-ce que le côté obscur est le plus fort ?
- non ! seulement plus facile, plus rapide, plus séduisant le côté obscur est.
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]
Hello,
Pour display_message,
ça ne fonctionnerait pas ? Car type_message ne semble pas optionnel... la doc me semble pas vraiment utile pour ce genre de méthode, son nom se suffit à elle même.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 def display_message(title: str, text: str, type_message: str) -> None: """Display a message box with the specified title, text, and type.""" getattr(QMessageBox, type_message)(None, title, text)
Mais au final, la question à se poser, c'est qui gagne-t-on comparé à l'utilisation directe de QMessageBox.warning ou QMessageBox.information ?
La structure du projet n'est pas très harmonieuse, mais au final on s'en fou un peu... parce-que c'est un petit projet, et que la maintenabilité est simple et qu'on s'y retrouve sans trop de difficulté.
Et je suis d'accord avec @papajoker, attention aux noms que l'on veut donner surtout quand on veut y apporter un sens, un modèle ou "domain" correspond généralement a la définition des entités métier...
L'esthétisme est bon, si c'est fonctionnel c'est top ! Mais on va pas se leurrer, ce code ne grossissant pas dans le futur, j'ai pas grand chose à en dire, sinon que l'essentiel est là, ça fonctionne !
EDIT :
Sve@r,
Je ne suis pas sûr de comprendre cette phrase, n'est-ce pas l'appel standard d'une fonction ou d'une méthode avec des arguments optionnels (sans les spécifier à nouveau) ?Autre chose: hériter de Qt c'est bien... mais cela ne doit pas faire perdre les avantages des objets d'origine (autrement dit, on préserve les objets et tous leurs paramètres)
Pour démontrer,
Je conserve bien tous les attributs de ma classe mère...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 class Test: def __init__(self, parent=None, x=5): # Même configuration que l'initialisation de QDialog (2 args optionnels) self.parent = parent self.x = x class NewTest(Test): def __init__(self, *args, **kwargs): super().__init__() nt = NewTest(2, 3, a=5, d="z") print(nt.parent) # None print(nt.x) # 5
Mais peut-être n'ai je pas compris où tu voulais en venir avec cette remarque ?
En fait, il nous manque une info ! Quelle est la logique derrière ce code ?pas grand chose à en dire, sinon que l'essentiel est là, ça fonctionne !
Si le but est juste qu'il fonctionne, alors ok pour le code
Si le but est de faire un "template" de bon code (je soupçonne avec les noms controleur et modele), alors c'est loupé.
- Qt a son propre système mvc (pour ce strict besoin, pas trop utile ici)
- Bloquer la taille des fenêtreset en plus, tu places les composants de façon statique
Et même si on fixe la taille de l'application/dialogues, dans tous les cas, on place/taille les composants relativement, par rapport au conteneur. On peut attribuer des marges si c'est cela qui te pose problème.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 pushButton_quit.setGeometry(QRect(758, 352, 68, 32)) utton_y = 168 self.gridLayoutWidget.setGeometry(QRect(8, 8, 585, 165)) QRect(int((self.width() / 2) - 34), 352, 68, 32) self.label_icon_application.setGeometry(QRect(758, 274, 68, 68))
Si tu crées un objet qui hérite d'un QDialog (ou de tout autre objet), ce que tu crées doit à minima offrir les mêmes possibilités que l'objet hérité (sinon on ne fait pas d'héritage). Prenons ton Test et NewTest, tu dois pouvoir utiliser NewTest au-moins exactement comme Test (ce qu'il fait en plus ne doit pas enlever ce que fait "Test").
Et justement ton NewTest tel que tu l'as écrit (avec *args et **kwargs) offre la possibilité de l'appeler comme Test et ça c'est bon. Mais si tu enlèves *args et **kwargs, tu es alors obligé de lui mettre des paramètres à l'image de ceux de Test (ce qui freine alors son évolutivité).
Evidemment (tout avantage amène souvent un inconvénient en retour) cela offre la possibilité d'appeler NewTest avec des paramètres non prévus comme dans ton exemple NewTest(2, 3, a=5, d="z"). Dans ce cas c'est Test qui doit checker et refuser "a" et "d" (comme le fera QDialog si tu l'appelles avec des paramètres non attendus).
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]
Mais on est bien d'accord que QDialog ne prend pas comme argument *args et **kwargs comme paramètres d'initialisation mais deux paramètres nommés et optionnels qui sont parent et f (flag) ?Et justement ton NewTest tel que tu l'as écrit (avec *args et **kwargs) offre la possibilité de l'appeler comme Test et ça c'est bon. Mais si tu enlèves *args et **kwargs, tu es alors obligé de lui mettre des paramètres à l'image de ceux de Test (ce qui freine alors son évolutivité).
Pour aller plus loin dans mon code, voilà ce que je peux être amené à faire sans perdre ni attribut ni méthode de Test.Evidemment (tout avantage amène souvent un inconvénient en retour) cela offre la possibilité d'appeler NewTest avec des paramètres non prévus comme dans ton exemple NewTest(2, 3, a=5, d="z"). Dans ce cas c'est Test qui doit checker et refuser "a" et "d" (comme le fera QDialog si tu l'appelles avec des paramètres non attendus).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 class NewTest(Test): def __init__(self, *args, **kwargs): super().__init__() self.arguments = args self.dictionary = kwargs nt = NewTest(2, 3, a=5, d="z") print(nt.parent) # None print(nt.x) # 5 print(nt.arguments) # (2, 3) print(nt.dictionary) # {'a': 5, 'd': 'z'}
Effectivement les termes sont mal choisis, et peut-être qu'il en ressort une incompréhension.Si le but est de faire un "template" de bon code (je soupçonne avec les noms controleur et modele), alors c'est loupé.
Tout à fait d'accord. *args et **kwargs tu le mets dans ton objet (d'ailleurs tu ne les as pas mis dans "Test" mais dans "NewTest" et ma toute première remarque s'appliquait à l'objet "UbuntuDesktopFileCategoriesView" de Diablo76) afin que l'utilisateur de ton objet puisse l'appeler avec les paramètres attendus par QDialog (pour avoir depuis ton objet le comportement de QDialog qu'il est en droit d'espérer).
Et c'est la magie de Python (ou plutôt l'unpacking) qui fait que puisque QDialog attend un paramètre "parent", si tu appelles UbuntuDesktopFileCategoriesView avec un paramètre "parent" ce paramètre sera transmis tel quel à QDialog. Et si tu ne le mets pas (effectivement c'est optionnel) ben il n'y aura pas de paramètre "parent" transmis.
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]
Salut !
@papajoker,
J'avoue ne pas avoir tout compris et savoir où tu voulais en venir avec ce code... est-ce que te concernant tu lies ce code a ce qui a été dit dans ma précédente conversation ?
Je l'ai testé avec PyQt6 n'ayant pas PySide6, cependant je ne vois pas concrètement ce que tu souhaites souligner, ni ce que techniquement on doit en retenir... Imaginons que tu expliques à un dev junior ce code, que doit-il en retenir et quelle expérience souhaite tu lui faire partager ? En plus, me concernant je suis une bille en Qt![]()
Ce code était uniquement la suite du message #25 : juste un code fonctionnel
ps: ne pas tenir compte que tout est dans le même fichierc'est uniquement par facilité pour ce forum
Je viens de voir ton code Arborescence…
Et je me rends compte que nous avons une vue sur QT complètement différente (Et donc ton bon exemple sur l'autre sujet ne me convient pas du tout).
Les models QT :
Pour moi, il est incompréhensible de s'en passer (sauf GUI extrêmement simple)
Exemple:
si j'utilise un modelQt, tout mes widgets attachés a lui vont être actualisés en temps réel
- si j'ai dans ma barre d'outil générale un filtre, l'autocomplétion va s'adapter dès que l'utilisateur ajoute un enregistrement (par exemple un filtre sur "ville"). Même chose si j'ai un combobox
Donc, avec un modèle, toutes les vues attachés sont mises à jour automatiquement au moindre changement.
Exemple:
Si j'utilise un modelQt, nous avons les proxy (datas aussi en temps réel). Un proxy peut servir pour un filtre, mais aussi pour fournir un "nouveau" modèle qui lui aussi est lié à notre modelQT de base
Exemple:
- Parfois, pour la gestion fine de l'affichage d'une cellule, nous avons QStyledItemDelegate qui reçoit un item(gui) lié à notre modèleQt
- avec un QItemDelegate (.setModelData exemples) particulier, je vais pouvoir lier notre modelQT à ce délégé pour un comboBox; exemple: delégé ne retourne qu'une seule colonne et affichée différemment pour ce combo: un combo (temps-réel) avec "ville+cp" tirés de notre modèle
Puisque je dois absolument utiliser les modelQT, si je veux avoir quand même un modèle python plus classique (utilisable en tests), j'ai donné une recette ici. Et ce modèle (classique*) python à la particularité d'envoyer des messages à la gui lors de modification (pas un refresh de la vue mais uniquement de la cellule)
*"classique" : pas vraiment dans ce cas car le cahier des charges du départ n'est pas classique (un seul enregistrement), j'ai juste voulu faire simple (minimum de lignes pour ce fichier) et relativement général (manque ajout et suppression)
Comme indiqué plus haut #21, pyside est la lib officielle de la société qui fournit QT. Je ne vois pas l'intérêt d'utiliser une lib non officielle
ps: ok, cela n'a que quelques années, mais en dev les choses évoluent, avant pyside était le vilain petit canard et pyqt la seule solution.
Ok je vois que tu es embêté avec le *args et **kwargs, je le retire
On est bien d'accord que NewTest a un intérêt en y ajoutant des attributs comme il a pu être fait sur la UbuntuDesktopFileCategoriesView ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 class NewTest(Test): def __init__(self): super().__init__() self.arguments = (2, 3) self.dictionary = {'a': 5, 'd': 'z'} nt = NewTest() print(nt.parent) # None print(nt.x) # 5 print(nt.arguments) # (2, 3) print(nt.dictionary) # {'a': 5, 'd': 'z'}
Note que Test prend la même configuration qu'un QDialog
je comprends Sve@r , c'est simplement le O du principe SOLID
Mais, ici dans cette appplication, je ne vois pas l'intéret :une entité applicative (classe, fonction, module ...) doit être fermée à la modification directe mais ouverte à l'extension
- c'est une classe finale
- cette classe ne sera jamais surchargée
- surtout, cette classe n'est utilisée que par un seul appel (je suppose donc que le dev a déjà passé tous ces bons paramètres). Et à la limite, si il désire changer un truc, c'est exactement le même travail de modification dans main ou le fichier de cette classe.
Si la classe était utilisée plusieurs fois et peut-être dans un contexte différent, alors oui, il faut l'Ouvrir au maximum.
Perso ? dans ce code, je ne passerais pas kwargs à cette class CategoriesDialog
EDIT:
Nous sommes bien d'accord, c'est un super principe. Mais le problème ici, c'est que tu n'as pas trop donné de raison. Le faire machinalement peut en être une...
C'est juste parce-que j'ai un PyQt6 sous la main, et que je ne souhaitais pas créer un nouvel environnement juste pour installer PySide6.Envoyé par papajoker
Non officielle ou pas, si elle existe c'est pour être utilisée... tout autant que PySide dans le temps où c'était le vilain petit canard.
Tu as beaucoup de termes où on sent un manque d'ouverture sur ce qui peut se faire dans le monde informatique ... "je ne vois pas l'intérêt, incompréhensible, je dois absolument"... si je te comprend bien, je jette PyQt6, la clean architecture n'a pas d'intérêt et je dois absolument utiliser les models Qt ?Envoyé par papajoker
Mais je ne comprend pas en quoi cette architecture empêche l'utilisation des models Qt, j'ai dû manquer quelque chose ? Je ne l'ai peut-être pas utiliser dans mon exemple, mais ça ne veut pas dire que je fais le choix de m'en passer dans d'autres cas !
N'importe quoi !Tu as beaucoup de termes où on sent un manque d'ouverture
je te dis que mon besoin est très différent du tien ! C'est pourtant clair ! Perso, j'ai besoin des modelQt dans 80% des cas (avec gtk c'est un autre système, les xxStore).
Donc, je persiste, pour moi, c'est un impératif d'utiliser les modèles natifs qt ou gtk.
Pour moi, renier une technologie est un manque d'ouverture ! moi, je dis, que je désire utiliser à mon maximum une techno. (c'est comme dire, je ne veux pas utiliser le css pour du web)je dois absolument utiliser les models Qt ?
Toi, dans ton exemple "clean architecture", tu zappes une technologie, je vais en déduire que tu as un manque d'ouverture ? (bien sûr que non) je peux juste te dire que ton exemple dans cet état ne me convient pas. L'architecture de ton exemple est très très bonne, j'ai dit le contraire ? c'est encore du n'importe quoi.la clean architecture n'a pas d'intérêt
Les 2 sont extrêmement proches en code, je souligne uniquement celle qui est officielle : beaucoup de personnes utilisent pyQt car c'est l'historique (sans connaitre pyside). Puisque tu disais ne pas trop bien connaitre Qt, c'était peut-être une chose que tu ne connaissais pas. ici aussi c'est du n'importe quoi, tu déformes une information en une demande/règle. Je développe encore parfois avec pyQt !si je te comprend bien, je jette PyQt6
J'ai parlé plusieurs fois de qml sur ce forum (en bien), tu en déduits que je cherche à l'imposer au détriment de pyqt et pyside ?![]()
Ben non, c'est justement la solution la plus efficace (et que je plébiscite) pour conserver l'héritage !!!
Bien sûr !!! Faire un héritage c'est pour avoir le beurre et l'argent du beurre. Mais il faut tout de même avoir le beurre.
Prends cet exemple: un objet "vehicule" (qui est présumé provenir d'une lib quelconque donc qui n'est pas de toi)
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 class vehicule: def __init__(self, vMax): self.vMax=vMax
Toi ton job est de créer un objet qui va hériter de véhicule (donc rajouter un truc "en plus", on va dire la marque, sans perdre les propriétés du véhicule).
Solution 1
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 class voiture(vehicule): def __init__(self, marque, vMax): super().__init__(vMax) self.marque=marque
L'utilisateur: vvv=voiture("marqueX", 200)...
Solution 2
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 class voiture(vehicule): def __init__(self, marque, *args, **kwargs): super().__init__(*args, **kwargs) self.marque=marque
L'utilisateur: vvv=voiture("marqueX", 200)...
Les deux solutions fonctionnent et sont utilisables de la même façon (y compris si l'objet de base a des paramètres facultatifs).
Mais la première impose de connaitre l'objet hérité (savoir ce qu'il attend pour reproduire les paramètres attendus dans ton objet). Et n'oublions pas que cet objet peut lui-même hériter d'un objet de plus haut niveau => obligé de tout connaitre pour créer un objet hérité correct.
Alors que la seconde est souple. Tu n'as pas à te préoccuper de "vehicule", tu lui passes "*args" et "**kwargs" sans te faire de noeud au cerveau et roule (c'est le cas de le dire).
Et en plus la seconde permet de suivre l'évolution. Si "vehicule" évolue...
... tu n'as pas besoin de modifier ton objet et c'est ça qui est important.
Code python : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 class vehicule: def __init__(self, vMin, vMax): self.vMin=vMin self.vMax=vMax
Je pars du principe que Diablo76 nous a demandé un avis, qu'il a envie d'apprendre des trucs qu'il ne sait pas forcément, et qu'il pourra les appliquer demain dans d'autres objets plus critiques. Pour résumer c'est juste "pour le principe"![]()
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]
Partager