Partage
  • Partager sur Facebook
  • Partager sur Twitter

Fonction : combien de jours dans le mois ?

Sujet résolu
10 mai 2019 à 18:28:56

Bonsoir, 

J'ai un problème avec ma fonction pour calculer, suivant le mois et l'année qu'on rentre, le nombre de jours présent dans celui ci.

En effet, ma fonction me renvoi toujours 30 sans prendre en compte les paramètres.

Pouvez vous m'aider ?

Merci.

#Q-Nombre de jours dans un mois
def nbre_jours (year,month):
      if month == 4 or 6 or 9 or 11:
            return(30)
      elif month == 1 or 3 or 5 or 7 or 8 or 10 or 12:
            return(31)
      elif (month == 2):
            if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
                  return(29)
            else:
                  return(28)
            



  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2019 à 18:52:18

Salut

Essaye de faire ça:

if 6:
    print('bonjour')

Tu verras que ça affichera bien "bonjour"

En fait ta condition n'effectue pas ce que tu veux essaye plutôt cela:

def nbre_jours(year,month):
    if month in [4, 6, 9, 11]:
        return(30)
    elif month in [1, 3, 5, 7, 8, 10, 12]:
        return(31)
    else:
        if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
            return(29)
        else:
            return(28)



  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2019 à 19:20:02

Ton code est équivalent à ceci en Python (le == a la priorité sur le or) :

def nbre_jours (year,month):
      if (month == 4) or 6 or 9 or 11:
            return(30)
      elif (month == 1) or 3 or 5 or 7 or 8 or 10 or 12:
            return(31)
      elif (month == 2):
            if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
                  return(29)
            else:
                  return(28)

month == 4 va retourner True ou False - quant à 6, en Python, 6 équivaut à True. Tu as donc quelque chose de la forme "b or True" qui vaut toujours True --> ton return 30 est toujours exécuté.

Ce que tu veux faire, c'est plutôt ça :

def nbre_jours (year,month):
      if (month == 4) or (month == 6) or (month == 9) or (month == 11):
            return(30)
      elif (month == 1) or (month == 3) or (month == 5) or (month == 7) or (month == 8) or (month == 10) or (month == 12):
            return(31)
      elif (month == 2):
            if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
                  return(29)
            else:
                  return(28)

Et là ça marche. Mais c'est assez répétitif - tu peux donc utiliser la solution de Codz_01 qui utilise la syntaxe "var in L", qui renvoie True si var est dans la liste L.


-
Edité par potterman28wxcv 10 mai 2019 à 19:20:44

  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2019 à 20:22:03

Le in c'est très bien, et c'est encore mieux avec un set plutôt qu'avec une liste (c'est plus rapide).

Sinon pour les fainéants comme moi il y a cette solution :

from calendar import monthrange

def nbre_jours(year, month):
    return monthrange(year, month)[1]



  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2019 à 20:26:56

Merci beaucoup à vous trois !

J'essaye de mettre un assert dans ma fonction pour cantonner l'utilisateur à prendre un chiffre entre 1 et 12, et j'ai toujours une erreur de syntaxe ! 

La fonction sans assert :

def nbre_jours(year,month):
    if month in [4, 6, 9, 11]:
        return(30)
    elif month in [1, 3, 5, 7, 8, 10, 12]:
        return(31)
    else:
        if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
            return(29)
        else:
            return(28)
      


Avec assert : 

def nbre_jours(year,month):
      assert (month == 1,2,3,4,5,6,7,8,9,10,11,12), "Month doit être copmpris entre 1 et 12"
    if month in [4, 6, 9, 11]:
        return(30)
    elif month in [1, 3, 5, 7, 8, 10, 12]:
        return(31)
    else:
        if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
            return(29)
        else:
            return(28)

Ca me met une erreur d'indentation. 

Je ne sais pas si je doit ouvrir un nouveau sujet, j'ai peur de polluer. 

A chaque fois je bloque, je regarde sur internet et fais des tests mais ça ne passe pas.

Là je ne vois pas pourquoi j'ai une erreur d'indentation alors que mon if est bien construit... ou pas.

Je n'ai plus d'erreur mais ça ne fonctionne pas :

def nbre_jours(year,month):
      assert (month !=0) , "Month doit être copmpris entre 1 et 12"
      assert (month <=12) , "Month doit être copmpris entre 1 et 12"
      if month in [4, 6, 9, 11]:
              return(30)
      elif month in [1, 3, 5, 7, 8, 10, 12]:
              return(31)
      else:
              if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
                  return(29)
              else:
                  return(28)
>>> nbre_jours(2016,13)
29




Romain

-
Edité par Fizzy59 10 mai 2019 à 21:28:12

  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2019 à 22:34:29

Dans ton premier code tu vois bien que la mot clef assert n'est pas indenté de la même façon que le return deux lignes plus loin...

Sinon je ne vois pas le problème de assert:

def nbre_jours(year, month):
    bon_mois = 0 < month < 13
    assert bon_mois, 'Wrong month'
    if month in [4, 6, 9, 11]:
        return 30
    elif month in [1, 3, 5, 7, 8, 10, 12]:
        return 31
    else:
        if year % 400 == 0 or (year % 4 == 0 and year % 100 != 0):
            return 29
        else:
            return 28



-
Edité par Codz_01 12 mai 2019 à 11:10:13

  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2019 à 23:01:45

Une tentative, j'ai pas testé sur tous les cas,

In [1]: def get_days(month, year): 
   ...:     if month in (4, 6, 9, 11): return 30 
   ...:     elif month == 2: 
   ...:         return 28 + (year%4 == 0 and (year%100 != 0 or year%400 == 0)) 
   ...:     return 31 
   ...:                                                                                   

In [2]: get_days(2, 2009)                                                                 
Out[2]: 28

In [3]: get_days(2, 2012)                                                                 
Out[3]: 29

In [4]: get_days(3, 2012)                                                                 
Out[4]: 31



  • Partager sur Facebook
  • Partager sur Twitter

Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

13 mai 2019 à 12:23:40

Merci, j'avance grâce à vous ! 

Me voila bloqué sur un autre problème,,qui me renvoi toujours True, même avec des valeurs qui ne sont pas comprises entre mes paramètres ! 

#Question Trouvez différents cas de non validité d’un triplet d’entiers pour représenter une date.

#Les mois en dessous de 1 et au dessus de 12
#Les jours en dessous de 1 et au dessus de 31
#L'année en dessous de 1

def est_date_valide (day,month,year):
    if 1 <= day <= 31:
        return True
    elif 1 <= month <= 12:
        return True
    elif year >= 1: 
        return True
    else:
        return False

Décidément....

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 13:31:32

Une fonction s'arrête après un return.

-
Edité par thelinekioubeur 13 mai 2019 à 13:31:46

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 14:22:02

def est_date_valide (day,month,year):
    if 1 <= day <= 31:
        print (True)
    elif 1 <= month <= 12:
        print (True)
    elif year >= 1: 
        print (True)
    else:
        print (False)


J'ai donc enlevé les return, merci pour le retour !
Mais ma fonction ne ... fonctionne toujours pas. 
  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 15:03:26

Fizzy59 a écrit:

def est_date_valide (day,month,year):
    if 1 <= day <= 31:
        print (True)
    elif 1 <= month <= 12:
        print (True)
    elif year >= 1: 
        print (True)
    else:
        print (False)

J'ai donc enlevé les return, merci pour le retour !
Mais ma fonction ne ... fonctionne toujours pas. 

Ta fonction affiche à l'écran True ou False, mais effectivement elle ne retourne rien du tout, c'est à dire qu'elle retourne None.

Tu avais bon avec tes instructions return du début. Mais tu ne retournais pas les bonnes choses.

Je rappelle la sémantique des if, elif, else :

if cond1:
  inst1
elif cond2:
  inst2
else:
  inst3

C'est équivalent à (en supposant que inst1 et inst2 ne modifient pas les conditions) :

if cond1:
  inst1
if (not cond1) and cond2:
  inst2
if (not cond1) and (not cond2):
  inst3

Ta fonction d'avant (avec les return) fait :

  • Si day est entre 1 et 31, c'est une date valide ! --> Par exemple, 04/42/-31 est une date valide.
  • Si day n'est pas entre 1 et 31, mais que month est entre 1 et 12, c'est une date valide ! --> Par exemple, -3/04/-31 est une date valide
  • Si day n'est pas entre 1 et 31, et month n'est pas entre 1 et 12, mais que year est plus grand que 1, c'est une date valide ! --> Par exemple, -3/42/1994 est une date valide.
  • Si day n'est pas entre 1 et 31 ET month n'est pas entre 1 et 12 ET year n'est pas plus grand que 1, ce n'est pas une date valide
Relis bien ça : est-ce que ça te semble être une spécification correcte ?
Si non, qu'est-ce que tu peux changer dans ces 4 lignes de français que j'ai écrites, de façon à ce que ça devienne correct ?



-
Edité par potterman28wxcv 13 mai 2019 à 15:05:09

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 16:00:56

  • Si day est entre 1 et 31, c'est une date valide ! --> Par exemple, 04/42/-31 est une date valide. Ca je garde.
  • Si day n'est pas entre 1 et 31, mais que month est entre 1 et 12, c'est une date valide ! --> Par exemple, -3/04/-31 est une date valide. Déjà, je remarque que ce n'est pas ça que je voudrais dire, je voudrais :

Que si le jour est compris entre 1 et 31, c'est bon ET que le mois est compris entre 1 et 12, c'es bon ET que l'année soit égale ou supérieur à 1 c'est bon MAIS si une ou plusieurs de ces conditions ne sont pas remplis, ce n'est pas bon.

Je comprend donc que les mots if, elif ne sont pas bon dans mon cas, est ce exact ?

Il faut un opérateur qui test, qui valide et puis passe au suivant, ou sinon lance que ce n'est pas bon.

Il me manque donc celui ci.

Il faudrait : and, et or ?

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 16:30:32

Tu as trois booléens :

(1 <= day <= 31) vaut True si le jour est valide, False sinon.

(1 <= month <= 12) vaut True si le mois est valide, False sinon.

(years >= 1) vaut True si l'année est valide, False sinon.

A partir de ces trois booléens, est-ce que tu peux m'indiquer une formule avec les opérateurs logiques booléens AND, NOT, OR qui renvoie True si la date est valide ?

-
Edité par potterman28wxcv 13 mai 2019 à 16:32:06

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 17:16:30

Merci @potterman

J'ai donc fait ça : 

def est_date_valide (day,month,year):
    if (1 <= day <= 31)and(1 <= month <= 12)and(year >= 1):
        return True
    else:
        return False

Ca fonctionne, mais je ne sais pas si c'est "optimisé" ou bien la bonne façon de faire ?

J'attaque la prochaine question :)

-
Edité par Fizzy59 13 mai 2019 à 17:19:40

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 17:35:40

Super ! :)

Est-ce que c'est optimisé ? Si un jour tu fais des calculs qui demandent énormément de ressources processeur, ou si tu fais des algorithmes compliqués (par exemple, trouver les meilleurs coups possibles dans une partie d'échec), tu pourras t'en soucier. Mais là, je dirais que ce n'est pas un problème. Il faut savoir que l'interpréteur Python fait déjà un certain nombre d'optimisations, donc si ça se trouve ton code est en fait déjà optimisé.

Est-ce que c'est la bonne façon de faire ? Absolument. C'est clair, et c'est ça que tu devrais garder en tête quand tu fais du code. Pour moi un bon code doit être :

  • Clair : en un coup d'oeil je dois être capable de voir ce que ça fait
  • Lisible : bonnes indentations, éviter les lignes de plus de 100 caractères, bien séparer les termes, mettre les bonnes parenthèses quand c'est pas évident
  • Robuste : les possibles bugs doivent être attrapés le plus tôt possible (pour l'instant t'en es pas à ce niveau, ça fera peut être sens plus tard), et les entrées (input) que donnent l'utilisateur ne doivent pas faire crasher le programme
  • Facile à maintenir : c'est à dire bien découper en fonctions, éviter les copier-coller - si tu as copié-collé une même série d'instructions 4 fois de suite c'est en général mauvais signe.

En terme d'espacement j'aurais écris ton code comme ça pour que ce soit un tout petit peu plus lisible mais c'est toi qui vois 

def est_date_valide (day, month, year):
    if (1 <= day <= 31) and (1 <= month <= 12) and (year >= 1):
        return True
    else:
        return False

Bon courage pour la suite :) Et n'oublie pas de mettre le sujet en résolu si tu penses qu'il est résolu.

-
Edité par potterman28wxcv 13 mai 2019 à 17:36:23

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 18:18:14

J'ai bien mis sujet résolu, si j'ai d'autres questions par la suite, je peux les poster ici pour ne pas encombrer le forum ?

Ou dois-je ouvrir un nouveau sujet ?

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 20:36:50

Ça dépend si la question est liée à toi de voir.

Sinon ta fonction est améliorable :

- les parenthèses sont inutiles

- le else est inutile après un return

- et surtout, ça ne prend pas en compte les mois de 28 à 30 jours. Or tu as déjà fais une fonction pour ça, autant l'utiliser :

def est_date_valide(day, month, year):
    if  year >= 1 and 1 <= month <= 12 and 1 <= day <= nbre_jours(year, month):
        return True
    return False

J'inverse l'ordre des tests car c'est plus logique de tester year et month avant de les utiliser dans nbre_jours.

On pourrait aussi ajouter quelque chose pour vérifier que day month et year sont bien des nombres entiers, à toi de voir.

-
Edité par thelinekioubeur 13 mai 2019 à 20:39:47

  • Partager sur Facebook
  • Partager sur Twitter
13 mai 2019 à 21:19:22

Par rapport à l'ordre des tests : Python est fainéant, c'est à dire que quand il évalue A and B, si A vaut False, il ne va pas évaluer B.

ça a donc du sens de mettre en premier ce qui est le plus évident. Mais c'est du détail.

  • Partager sur Facebook
  • Partager sur Twitter
14 mai 2019 à 2:02:42

thelinekioubeur a écrit:

def est_date_valide(day, month, year):
    if  year >= 1 and 1 <= month <= 12 and 1 <= day <= nbre_jours(year, month):
        return True
    return False
qu'on écrit plutôt :
def est_date_valide(day, month, year):
    return  year >= 1 and 1 <= month <= 12 and 1 <= day <= nbre_jours(year, month):
        

-
Edité par PascalOrtiz 14 mai 2019 à 2:02:56

  • Partager sur Facebook
  • Partager sur Twitter
27 mai 2022 à 1:37:54

@YOUSSEFSAHARA:
Tu déterres un sujet de 2019. Peux-tu poster ton propre sujet?
Postes ton code. Pas de saisie d'écran.
Donnes plus d'explication.
  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

27 mai 2022 à 4:23:58

@YOUSSEFSAHARA Bonsoir, merci de ne pas déterrer d'ancien sujet résolu. Créer le votre dans le respect des règles du forum à savoir qu'un message commence par des règles de politesses (un bonjour ou des salutations à la communauté et se termine par des remerciements par avance pour les futures réponses) un descriptif de votre problème et le code que vous avez écrit inséré sur le forum avec l'outil d'intégration de code soit le bouton code </>.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter