Cette fonction dis : après x ms tu exécute tel fonction.
after(parent, ms, function = None, *args)
Ici je m'en sert pour simuler la chute d'un corps, a chaque itération la méthode after appel une fonction qui décale légèrement un objet en y et en le répétant plein de fois, l'objet chute.
Le problème c'est que quand je lance le programme j'appel plusieurs fois la fonction qui fait tourner les itérations de after et à chaque appel le délai d’exécution d'after diminue (je le constate visuellement uniquement car ma variable t_delais reste constante)
EtienneDubs a écrit:
Cette fonction dis : après x ms tu exécute tel fonction.
after(parent, ms, function = None, *args)
Ici je m'en sert pour simuler la chute d'un corps, a chaque itération la méthode after appel une fonction qui décale légèrement un objet en y et en le répétant plein de fois, l'objet chute.
Le problème c'est que quand je lance le programme j'appel plusieurs fois la fonction qui fait tourner les itérations de after et à chaque appel le délai d’exécution d'after diminue (je le constate visuellement uniquement car ma variable t_delais reste constante)
Tu ne peux pas fournir ton code complet pour que je puisse le lancer dans la console ? Ca serait plus simple à debogger (au min faire un code minimal qui marche et montre le bug ) . Je suis un peu perdu dans tes variables et dans les fonctions qui appelle d'autres fonctions .
Ca me surprend que ta fonction deplacement_vertical ne prend pas d'autre paramètres ...
from tkinter import *
from math import sin, cos, pi
from random import randrange,choice,randint
#import matplotlib.pyplot as plt
haut=500 #1 pixel = 1m irl
larg=1000
class Fusee:
"""Fusee"""
def __init__(self,boss,sol):
self.boss = boss#mémorisation de la frame de référence
self.sol=sol#récupétaion de l'objet sol
self.x0 = randrange(0,larg) #position en x de la fusee
self.y0=0 #position en y de la fusee
self.hfusee=40 #hauteur de la fusée
self.lfusee=15 #largeur de la fusee
self.fusee = self.boss.create_rectangle(self.x0,self.y0,self.x0+self.lfusee,self.hfusee, fill = 'blue')
self.chute_libre=True
self.gaz_on=False
self.t=0 #temps
self.vy=0 #vitesse verticale initiale
self.t_delais=20
self.nb_changement_de_direction=0
self.gravite_fusee()
def gravite_fusee(self):
gravitee =1 #en m/s²
self.acceleration=gravitee
self.t = 0
if self.gaz_on==True:#suprime l'oval représenteant les gaz
self.boss.delete(self.gaz)
self.gaz_on=False
self.deplacement_verticale()
self.nb_changement_de_direction+=1
def etteindre_gaz(self,event):
self.gravite_fusee()
def mettre_les_gaz(self,event):
moteur = -1 #en m/s²
self.acceleration=moteur
self.t=0
if self.gaz_on==False:#Crée un oval représentant les gaz uniquement si la fusee était en chute libre
self.gaz = self.boss.create_oval(self.x0,self.y0+self.hfusee-10,self.x0+self.lfusee,self.y0+self.hfusee+self.hfusee/3,fill='red')
self.chute_libre=False
self.gaz_on=True
self.deplacement_verticale()
self.nb_changement_de_direction+=1
def deplacement_verticale(self):
self.boss.move(self.fusee,0,self.vy)
self.y0+=self.vy
verif_aterissage=self.sol.atterissage()
if verif_aterissage==False:
self.boss.after(self.t_delais,self.deplacement_verticale)
else:
self.fin_du_vol()
if self.chute_libre==False:#déplace les flammes de la fusée avec la fusée
self.boss.move(self.gaz,0,self.vy)
self.t+=1 #Evolution du temps
self.vy+=self.acceleration/100 #Vitesse verticale en m/s
def deplacement_droite(self, event):
self.direction_hor='droite'
self.deplacement_horizontal()
def deplacement_gauche(self,event):
self.direction_hor='gauche'
self.deplacement_horizontal()
def deplacement_horizontal(self):
if self.direction_hor == 'droite':
self.vx=10
elif self.direction_hor=='gauche':
self.vx=-10
if self.gaz_on==True:#déplace les flammes de la fusée avec la fusée
self.boss.move(self.gaz,self.vx,0)
self.boss.move(self.fusee,self.vx,0)
self.x0+=self.vx
#def deplacement_fusee(self)
def changer_position_fusee(self):#changer la position au départ
deplacement_possible_x_pos=larg-self.x0
deplacement_possible_x_neg=0-self.x0
deplacement_possible_x=randrange(deplacement_possible_x_neg,deplacement_possible_x_pos)
self.x0=self.x0+deplacement_possible_x
self.boss.move(self.fusee,deplacement_possible_x,0)
def fin_du_vol(self):
print("La fusee a atterie")
self.boss.move(self.fusee,self.vx,0)
class Sol:
def __init__(self,boss):
self.boss = boss
self.sol_avant=[]#création du sol avant zone d'atterissage
self.sol_apres=[]#création du sol apres zone d'atterissage
self.sol_atterissage=[]
self.lvl=1
self.terrain_lvl3()
self.creer_zone_d_aterrissage()
def terrain_lvl1(self):
self.boss.create_line(0,haut*0.9,larg,haut*0.9)
print('création du terrain')
def terrain_lvl2(self):
self.taille_zone_d_aterrissage=75
self.longeur_bloc_possible_y=[5,25,50,75,100]
def terrain_lvl3(self):
self.taille_zone_d_aterrissage=50
self.longeur_bloc_possible_y=[-50,-75,-100,-150,-200,50,75,100,150,200]
def generer_lvl(self):#a finaliser
self.taille_zone_d_aterrissage-=self.lvl
def creer_zone_d_aterrissage(self):
self.zone_d_aterrisage_x0=randrange(0,larg)
self.zone_d_aterrisage_y0=randrange(0.7*haut,haut*0.8)
self.zone_d_aterrisage_x1=self.zone_d_aterrisage_x0+self.taille_zone_d_aterrissage
self.zone_d_aterrisage_y1=self.zone_d_aterrisage_y0
self.creer_sol()
self.zone_d_aterrisage = self.boss.create_rectangle(self.zone_d_aterrisage_x0,self.zone_d_aterrisage_y0,self.zone_d_aterrisage_x1,self.zone_d_aterrisage_y1+1,fill='red',width=10)#,capstyle='round')
def creer_sol(self):
#création ddu sol après la zone d'aterrisage
x0=self.zone_d_aterrisage_x0
y0=self.zone_d_aterrisage_y0
y0_sens=1
for i in range(self.zone_d_aterrisage_x0,0,-1):
if randrange(0,100)==100 or y0>0.9*haut:
y0_sens=-1
elif randrange(0,100)==100 or y0<0.4*haut:
y0_sens=1
x0-=1
self.sol_avant.append(x0)
y0+=1*y0_sens
self.sol_avant.append(y0)
#création ddu sol après la zone d'aterrisage
x0=self.zone_d_aterrisage_x1
y0=self.zone_d_aterrisage_y1
y0_sens=1
for i in range(self.zone_d_aterrisage_x1,larg,1):
if randrange(0,50)==1 or y0>0.9*haut:
y0_sens=-1
elif randrange(0,50)==2 or y0<0.4*haut:
y0_sens=1
x0+=1
self.sol_apres.append(x0)
y0+=1*y0_sens
self.sol_apres.append(y0)
couleur_ligne="#%02x%02x%02x" %(randint(0,255),randint(0,255),randint(0,255))
self.boss.create_line(self.sol_avant,joinstyle='round',width=8,fill=couleur_ligne)
self.boss.create_line(self.sol_apres,joinstyle='round',width=8,fill=couleur_ligne)
def atterissage(self):
atterrisage=False
if len(self.boss.find_overlapping(self.boss.coords(self.zone_d_aterrisage)[0]+2,
self.boss.coords(self.zone_d_aterrisage)[1],
self.boss.coords(self.zone_d_aterrisage)[2]-2,
self.boss.coords(self.zone_d_aterrisage)[3]))>1:
atterrisage=True
return atterrisage
class Pupitre:
def __init__(self,master,fusee):
self.master=master
self.fusee=fusee
Button(self.master,text='faire chuter la fusée',command=self.fusee.gravite_fusee).pack(side=RIGHT)
#Button(self.master,text='deplacer la fusee point de départ',command=self.fusee.changer_position_fusee).pack()
Button(self.master,text='Mettre les gaz',command=self.fusee.mettre_les_gaz).pack(side=LEFT)
class Application(Frame):
'''Fenêtre principale de l'application'''
def __init__(self,haut,larg):
Frame.__init__(self)
self.master.title('>>>>> SpaceShip Landing <<<<<')
#self.master.geometry('720x720')
self.pack()
self.jeu = Canvas(self, width =larg, height =haut, bg ='ivory', bd =3, relief =SUNKEN)
self.jeu.pack()#(padx =8, pady =8, side =TOP)
#self.fusee.chute_libre()
#Création d'un sol
self.sol_a_creer= Sol(self.jeu)
#Création d'une fusée
self.arianne = Fusee(self.jeu,self.sol_a_creer)
#Création du pupitre qui contrôle
self.pupitre_a_creer = Pupitre(self,self.arianne)
self.jeu.bind_all('<Left>', self.arianne.deplacement_gauche)
self.jeu.bind_all('<Right>', self.arianne.deplacement_droite)
self.jeu.bind_all('<Up>', self.arianne.mettre_les_gaz)
self.jeu.bind_all('<Down>', self.arianne.etteindre_gaz)
if __name__ =='__main__':
Application(haut,larg).mainloop()
Bon je vous mets tout en mode brut pour être sût que l'on ai bien la même chose.
Désolé si la rédaction n'est pas très belle, c'est un de mes premiers code...
def deplacement_verticale(self):
self.boss.move(self.fusee,0,self.vy)
self.y0+=self.vy
verif_aterissage=self.sol.atterissage()
if verif_aterissage==False:
self.boss.after(self.t_delais,self.deplacement_verticale)
else:
self.fin_du_vol()
if self.chute_libre==False:#déplace les flammes de la fusée avec la fusée
self.boss.move(self.gaz,0,self.vy)
self.t+=1 #Evolution du temps
self.vy+=self.acceleration/100 #Vitesse verticale en m/s
print (self.t_delais)
Ta fonction fonctionne parfaitement . Le delais de recursivité de la fonction deplacement verticale ne diminue pas mais reste constant (20) .
Tu te déplaces en y de self.vy Ca se deplace très lentement car tu ajoutes juste 1/100 à self.y
Le problème est que tu dois appeler une deuxième fois la fonction déplacer vertical (via les fonctions mettre les gaz et gravité_fusé) ... Je pense que ton code n'est pas optimisé et que ca ne devrait pas être possible ....
J'utilise cette solution qui devrait te convenir dans ton cas .
Ta phrase n'est pas encadrée entièrement pas des apostrophes (aime le pithon) . Il a juste compris que chaine contient la phrase J ,il se demande pourquoi tu rajoute des caractères après .
Les véritables syntaxe sont :
chaine = 'Jaime le Python'
ou
chaine = 'J\'aime le Python'
\ avant ' signifie qui faut prendre le caractère ' comme du text et non comme une syntaxe python
Je ne comprends pas comment sont enregistrées les données dans self._cles et self._valeurs. A quels moment de la Class les données de "base" et de "**données" sont mis en paramètre de ces listes ?
self[cles]=base[cles], cela veut dire que self prends tout le dictionnaire mais ne dissocie pas les clés des valeurs.
Je ne comprends pas comment sont enregistrées les données dans self._cles et self._valeurs. A quels moment de la Class les données de "base" et de "**données" sont mis en paramètre de ces listes ?
self[cles]=base[cles], cela veut dire que self prends tout le dictionnaire mais ne dissocie pas les clés des valeurs.
C'est assez confus pour moi.
Merci d'avance pour vos réponses
def __init__(self, base={}, **donnees) signifie que tu as deux paramètres (base et **donnees)
Le paramètre base est optionnelle car si tu ne le renseigne pas base ={}
Le second paramètre **donnees est aussi optionnelle , c'est un paramètre kwargs (type dictionnaire),:
-les ** signifie que tu crée un dictionnaire nommé donnees . donnees = {} par defaut . Tu peux donc ne pas renseigner de paramètre .
-Vu que le paramètre est de type dictionnaire (kwargs),tu dois utiliser cette syntaxe : macle = "mavaleur" .
-Tu peux mettre plusieurs clé/valeur dans données en séparant par des virgules : macle="valeur",autre="deuxiemecle"
Ex:
DictionnaireOrdonne({"macle":"mavaleur"}) #j'ai juste renseigné base qui vaut {"macle":"mavaleur"}, donnees = {} par défaut
DictionnaireOrdonne({"macle":"mavaleur"},unecle = "melon") #j'ai renseigné base qui vaut {"macle":"mavaleur"} et donnees = {"unecle": "melon,"autre":2}
C'est de cette manière que tu renseignes les clé et valeur dans le dictionnaire .
Ton but sera de creer deux listes (une avec les clé et l'autre avec les valeurs) .Il faudra donc parcourir base et donnees et séparer les clés/valeur dans deux listes distinctes.
Je ne te conseille pas d'utiliser la méthode de la correction du tuto qui est juste tordu (voir ci -dessous) car tu passes par la méthode spéciale _getitem__ .de dictionnaireordonne .Ce n'est pas très logique ...
Bon courage .
for cle in base:
self[cle] = base[cle]
# On récupère les données de 'donnees'
for cle in donnees:
self[cle] = donnees[cle]
def __getitem__(self, cle): """Renvoie la valeur correspondant à la clé si elle existe, lève une exception KeyError sinon"""
if cle not in self._cles: raise KeyError( \ "La clé {0} ne se trouve pas dans le dictionnaire".format( \ cle)) else: indice = self._cles.index(cle) return self._valeurs[indice]
Merci pour ta réponse détaillée, j'avais très bien compris le début de ton explication. J'ai également bien compris que self devient le dictionnaire passé en paramètre.
Voilà ce que j'ai commencé à faire :
class DictOrdo:
def __init__(self, dict={}, **donnees):
self._index = []
self._value=[]
for cle, valeur in dict.items():
self._index.append(cle)
self._value.append(valeur)
for cle, valeur in donnees.items():
self._index.append(cle)
self._value.append(valeur)
Ce n'est pas du tout la même la chose, est ce que je suis sur une bonne piste meme si c'est différent ou est ce que je fais fausse route?
J'ai eu un peu de mal à lire ton bout de code car il n'a pas été bien mise en forme par le forum
class DictOrdo:
def __init__(self, dict={}, **donnees):
self._index = []
self._value=[]
for cle, valeur in dict.items():
self._index.append(cle)
self._value.append(valeur)
for cle, valeur in donnees.items():
self._index.append(cle)
self._value.append(valeur)
C'est presque parfait
dict={} # le terme dict est un mot spécial dans python .Evite de l'employer en paramètre même si ca fonctionne
Il faut aussi vérifier que le paramètre dict (base c'est mieux) est bien sous forme de dictionnaire .
Si je rentre a = DictOrdo ("b") . Ca va faire planter ta boucle
Le code que tu as crée est sinon parfait . Tu as remplis la première régle du TP ci dessous .Tu es sur la bonne voie
On doit pouvoir créer le dictionnaire de plusieurs façons :
Vide : on appelle le constructeur sans lui passer aucun paramètre et le dictionnaire créé est donc vide.
Copié depuis un dictionnaire : on passe en paramètre du constructeur un dictionnaire que l'on copie par la suite dans notre objet. On peut ainsi écrireconstructeur(dictionnaire)et les clés et valeurs contenues dans le dictionnaire sont copiées dans l'objet construit.
Pré-rempli grâce à des clés et valeurs passées en paramètre : comme les dictionnaires usuels, on doit ici avoir la possibilité de pré-remplir notre objet avec des couples clés-valeurs passés en paramètre (constructeur(cle1 = valeur1, cle2 = valeur2, …)
Je comptais m'occuper de la vérification du type de données passées en paramètre un peu plus tard car ça ne me semblait pas difficile.
Je voulais d'abord m'attaquer à ce qui me paraissait le plus difficile en premier
Pourquoi :
def __getitem__(self, cle):
if cle not in self._index:
raise KeyError( \
"La clé {0} ne se trouve pas dans le dictionnaire".format( \
cle))
Me renvoie une erreur de syntaxe comme celle-ci,
b["banane"]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/run/media/guillaume/Données/Documents/Programmes/DictOrdo.py", line 24, in __getitem__
cle))
KeyError: 'La clé banane ne se trouve pas dans le dictionnaire'
je ne comprends pas ce que je fais de mal avec ma syntaxe.
class DictOrdo:
def __init__(self, dict={}, **donnees):
self._index = []
self._value=[]
for cle, valeur in dict.items():
self._index.append(cle)
self._value.append(valeur)
for cle, valeur in donnees.items():
self._index.append(cle)
self._value.append(valeur)
def __getitem__(self, cle):
if cle not in self._index:
raise KeyError("La cle {} ne se trouve pas dans le dictionnaire".format(cle))
else:
print ("j'ai bien {} dans mon dico".format(cle))
Après trois test ,ca fonctionne correctement .
a=DictOrdo ({"poubelle":2},machin ="truc")
>>> a["poubelle"]
j'ai bien poubelle dans mon dico
>>> a["machin"]
j'ai bien machin dans mon dico
>>> a["bidule"]
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
a["bidule"]
File "C:\Users\Charles\Desktop\canvas - Copie.py", line 20, in __getitem__
raise KeyError("La cle {} ne se trouve pas dans le dictionnaire".format(cle))
KeyError: 'La cle bidule ne se trouve pas dans le dictionnaire'
Tu as cette erreur car tu n'as pas la clé "banane" et c'est toi qui l'a ecrit dans ton code via:
if cle not in self._index:
raise KeyError("La cle {} ne se trouve pas dans le dictionnaire".format(cle))
Dans l'intro, au chapitre 4, au moment où sont exposées les limites de la fonction if, quand j'essaye de reproduire les lignes de code : 1) >>> a = 5 2) >>> if a > 0: # Si a est positif 3) ... print("a est positif.") 4) ... if a < 0: # a est négatif 5) ... print("a est négatif.")
Je n'arrive pas à rentrer la 5ème ligne, quand j'appuie sur entrée à la fin de la 4ème ligne pour donner la dernière instruction, Paf l'interpréteur m'affiche direct un message d'erreur : File "<stdin>", line 3 if a<0: ^ SyntaxError: invalid syntax
Dans ce cours, il faut faire pleins de test avec pytest.
Le code à tester:
class Agent:
def __init__(self, position, **properties):
self.position = position
for property_name, property_value in properties.items():
setattr(self, property_name, property_value)
On cherche à voir si il y a bien un dictionnaire qui est assigné en tant qu'attribut de classe.
D'après le cours, voici le code qui permet de tester à l'aide de pytest:
import ~nom_du_programme~ as script
#assigner un dictionnaire en tant qu'attributs
def test_set_agent_attributes():
agent = script.Agent(3, agreeableness=1)
assert agent.agreeableness == 1
Ma question est la suivante: En quoi ce teste vérifie qu'il s'agisse bien d'un dict ?
A mon sens, on regarde uniquement que sa valeur ==1
Je suis en train de terminer mon dictionnaire ordonné. Ma fonction add marche très bien mais j'ai voulu y ajouter une vérification afin que le 2ème objet ajouté soit bien dictionnaire ordonné.
Seulement j'ai beaucoup de mal avec la fonction type().
En regardant la solution j'ai vu ceci mais je ne comprends pas quelle vérification il fait...
def __add__(self, autre_objet):
"""On renvoie un nouveau dictionnaire contenant les deux
dictionnaires mis bout à bout (d'abord self puis autre_objet)"""
if type(autre_objet) is type(self):
raise TypeError( \
"Impossible de concaténer {0} et {1}".format( \
type(self), type(autre_objet)))
else:
nouveau = DictionnaireOrdonne()
# On commence par copier self dans le dictionnaire
for cle, valeur in self.items():
nouveau[cle] = valeur
# On copie ensuite autre_objet
for cle, valeur in autre_objet.items():
nouveau[cle] = valeur
return nouveau
Comme je le comprends il lève une erreur si les 2 objets sont de même type, mais en fait quand je teste ça ne se passe pas comme ça.
S'il n'y a pas de solution, c'est qu'il n'y a pas de problème.
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
Après trois test ,ca fonctionne correctement .
entwanne — @entwanne — Un zeste de Python — La POO en Python — Notions de Python avancées — Les secrets d'un code pythonique
S'il n'y a pas de solution, c'est qu'il n'y a pas de problème.