Vendredi 13 sur Hackinscience

Bonjour tout le monde !

En plein apprentissage de Python, j’ai commencé les exercices proposés sur Hackinscience. Là, je suis arrivé à celui qui s’appelle “Vendredi 13”. J’ai écrit cette version qui semble tourner à perfection quand je l’exécute sur mon pc avec Visual Studio et Python 3.12.

Je précise que la dernière ligne me sert juste à faire mes tests en local.

Pourriez vous m’expliquer - simplement - pourquoi le code ne fonctionne pas une fois envoyé sur Hackinscience ? J’ai le message suivant :

TypeError: FakeDatetime.date() takes 1 positional argument but 4 were given

Je trouve ça un peu étrange car je n’ai pas utilisé cette fonction, et je ne savais même pas qu’elle existait.

Voici mon code :

# Vendredi 13

import datetime

def friday_the_13th():
    # date actuelle
    aujourdhui = datetime.datetime.now()    
    jour = int(aujourdhui.strftime('%d'))
    mois = int(aujourdhui.strftime('%m'))
    annee = int(aujourdhui.strftime('%Y'))
 
    # on teste si aujourd'hui, nous sommes un vendredi 13
    if jour == 13 and aujourdhui.date(annee, mois, jour).weekday() == 4:
        vendredi13 = str(annee) + "-" + str(mois) + "-13"
    else:   
        # sinon, on boucle sur les 13 des mois successifs
        # pour voir si ça tombe un vendredi 
        
        while datetime.date(annee, mois, 13).weekday() != 4:
            if mois < 12:
                mois += 1
            elif mois == 12:
                mois = 1
                annee += 1
                
        # le prochain vendredi 13
        # avec un ajustement sur le mois pour l'avoir avec 2 chiffres       
        mois = str(mois).rjust(2, "0")
        vendredi13 = str(annee) + "-" + str(mois) + "-13"
        
        return vendredi13
    
# test
print(friday_the_13th())

Bonjour,

Que t’attends-tu à avoir lorsque tu fais aujourdhui.date(annee, mois, jour)?

aujourdhui est un objet datetime, il possède bien une méthode date (pour récupérer la date associée) mais cette méthode ne prend par d’arguments.

J’avais cru comprendre que c’était un moyen de définir la date sur laquelle on est en train de travailler. :pensive:

Bonjour !

C’est moi qui ai rédigé cet exercice :wink:

Je comprend que ça fasse bizarre. C’est parce que pendant mes tests, je vérifie que ta fonction fonctionne bien si on la lance aujourd’hui, comme tu t’en doute, mais je vérifie aussi qu’elle fonctionnera dans le futur. Je fais plusieurs tests.

Pour ça j’utilise une bibliothèque nommée freezegun, c’est elle qui remplace la vraie date par une “Fake” date.

Quant à ton problème, je suis très surpris que ton code fonctionne sur vscode, que t’affiche-il ?

Chez moi avec un Python 3.12 :

>>> import datetime
>>> aujourdhui = datetime.datetime.now()
>>> aujourdhui.date(2023, 11, 28).weekday()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: datetime.date() takes no arguments (3 given)

@entwanne a raison, la méthode date() n’accepte pas d’arguments.

Tu semble confondre le module datetime et la classe datetime. C’est normal, ils ont le même nom.

Le module datetime tu l’obtiens via import datetime, et la classe datetime via datetime.datetime (par exemple quand tu fais datetime.datetime.now()).

Un bon moyen de ne pas se mélanger les pinceaux c’est de renommer le module datetime en dt à l’import, en plus c’est plus court à taper :

import datetime as dt

Comme ça plus d’ambiguité : dt c’est le module, dt.datetime c’est la classe.

Ainsi tu peux faire :

import datetime as dt

aujourdhui = dt.datetime.now()
annee = aujourdhui.year
mois = aujourdhui.month
jour = aujourdhui.day

print(aujourdhui)

demain = dt.date(annee, mois, jour + 1)

print(demain)

Note que je n’utilise pas la méthode date de la classe datetime mais la classe date du module datetime (nommé dt).

Ahh aussi note que mes maths sont toutes pétées, jour + 1 c’est plutôt risqué, ça explosera au 32ème jour du mois, mais c’était pour l’exemple :wink:

1 « J'aime »

Aaaah d’accord ! Je crois que j’ai compris, j’ai l’impression que c’est un peu comme si j’avais confondu un contenu et un contenant qui auraient le même nom.

Je prends note que c’est plus pratique de renommer les modules !

Quoi qu’il en soit, j’ai pu envoyer un code fonctionnel sur Hackinscience ! Je vais juste voir si je peux l’améliorer, car j’ai quelques années d’expérience en programmation, mon instinct me dit que mon code est trop long, et qu’il a besoin d’être simplifié.

Je n’ai pas gardé le code, mais j’ai une capture d’écran de Visual Studio, avec une exécution dans la console. Le code est globalement celui que j’avais mis dans mon premier message, mis à part des changements au niveau des print pour me rapprocher du problème demandé.

Je me suis rendu compte après coup qu’il ne fonctionne pas dans tout un tas de cas à cause de mon while qui est codé avec les pieds.

Ohhh je vois, c’est magique, voilà pourquoi ton code fonctionne : on est pas un 13.

@entwanne et moi nous étions arrêtés à la ligne :

if day == 13 and today.date(year, month, day).weekday() == 4:

en notant que today.date() n’accepte pas ces arguments…

Mais nous sommes le 28, pas le 13, et donc pour Python, lorsqu’il voit day == 13 and ... s’arrête net, pas besoin de continuer à évaluer, c’est faux dans tous les cas, (False and True et False and False sont tous les deux faux) donc pas de plantage à cette ligne.

Preuve :

>>> if 1 == 2 and this_function_does_not_even_exist():
...     pass
... 

pas de platage !

Et le reste de ton code utilisait datetime.date(year, month, 13), ce qui est juste (ça crée une instance de la class date du module datetime), donc ça marchait chez toi.

Et une fois sur HackInScience, hop, je fais plein de tests, des vendredis pas 13, des 13 pas vendredi, des veilles de vendredi 13, des lendemains, etc, etc…

Un de ces cas tombait donc sur day == 13, amenant Python à évaluer la partie de droite, après le if, celle qui ne fonctionne pas.

4 « J'aime »