IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Une fonction crée_vaisseau qui ne trouve pas un attribut d'une classe.


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    sans
    Inscrit en
    Mai 2023
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Mai 2023
    Messages : 316
    Par défaut Une fonction crée_vaisseau qui ne trouve pas un attribut d'une classe.
    Salut


    Ma classe Humain contient bien l'attribut Camp mais une fonction ne trouve pas cet attibut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Humain(C_player) :
        def __init__(self) :
            super().__init__()
            # ***************** Caractéristiques ***************
            self.Nom="Humain"
            self.Camp=0
    La fonction qui ne sait pas trouver l'attribut Camp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def Cree_vaisseau(nom,arme) :
     
        # Attribue la classe Vaisseau()
        vaisseau = Vaisseau
     
        vaisseau.Nom=nom
     
        # Définit les armes voulues.
        vaisseau.Armes=arme
     
        if joueur.Camp==0 :
            # Etc....
    Le message d'erreur :

    if joueur.Camp==0 :
    AttributeError: type object 'Humain' has no attribute 'Camp'


    EDIT :

    Apparement, j'ai plus le message d'erreur après avoir ajouté des parenthèses ici : vaisseau = Vaisseau()

    Qu'en dites-vous ?

  2. #2
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 108
    Par défaut
    J'en dit que les majuscules sont mal utilisées et que ça serait plus clair si on avait une idée du type de jeu concerné.
    Quelle est l'utilité d'une fonction cree_vaisseau s'il existe déjà une classe Vaisseau ?

  3. #3
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    5 011
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 011
    Par défaut
    Hello,

    Le message d’erreur donne une indication importante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    AttributeError: type object 'Humain' has no attribute 'Camp'
    La partie type object 'Humain' signifie que joueur référence probablement la classe Humain elle-même, et non une instance de cette classe.

    Vous devez sans doute avoir quelque chose de ce genre :

    Dans ce cas, la méthode init() n’est jamais exécutée, donc l’attribut Camp n’est pas créé.

    Il faut instancier la classe avec des parenthèses :

    Votre attribut étant défini ainsi :

    il appartient aux instances de Humain, et non directement à la classe Humain.

    C’est exactement le même problème avec cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    vaisseau = Vaisseau
    Elle ne crée pas de vaisseau : elle place simplement la classe Vaisseau dans la variable vaisseau.

    La bonne écriture est donc bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    vaisseau = Vaisseau()
    Mais cette correction ne peut pas, à elle seule, corriger l’erreur concernant joueur.Camp. Il faut également vérifier comment la variable joueur est initialisée.

    Votre fonction pourrait par exemple être écrite ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    def cree_vaisseau(nom, arme, joueur):
        vaisseau = Vaisseau()
        vaisseau.nom = nom
        vaisseau.armes = arme
     
        if joueur.camp == 0:
            # ...
            pass
     
        return vaisseau
    Et appelée de cette manière :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    joueur = Humain()
    vaisseau = cree_vaisseau("Mon vaisseau", arme, joueur)
    À noter également que, selon les conventions Python, on utilise généralement :

    • Humain et Vaisseau pour les noms de classes ;
      cree_vaisseau, joueur, nom, armes et camp pour les fonctions, variables et attributs.


    Enfin, concernant la remarque de josmiley, une fonction cree_vaisseau() peut être utile si elle joue le rôle de fabrique et contient une logique de création particulière. Si elle ne fait qu’appeler Vaisseau() et affecter deux attributs, il serait probablement plus simple de passer ces informations directement au constructeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    class Vaisseau:
        def init(self, nom, armes):
            self.nom = nom
            self.armes = armes
    Puis :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    vaisseau = Vaisseau("Mon vaisseau", arme)

  4. #4
    Membre éclairé
    Homme Profil pro
    sans
    Inscrit en
    Mai 2023
    Messages
    316
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Mai 2023
    Messages : 316
    Par défaut
    merci beaucoup Fred, comme chaque fois tes réponses sont toujours des supers cours où j'apprend des choses !!! J'ai bien fais de poser la question

    Joesmiley, salut !
    c'est un shooter, le jeu, et l'utilité de la fonction vaisseau est de créer des instances d'un type de vaisseau mais avec une logique particulière comme l'a ainsi nommée Fred.
    vala, vala...

  5. #5
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 108
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 108
    Par défaut
    Je veux bien s'il s'agit de créer un vaisseau de façon interactive, le joueur choisi les caractéristiques par exemple, sinon je ne vois pas vraiment. La fonction retournera une instance de Vaisseau normalement, à moins qu'elle initialise en plus des variables plus globales, auquel cas elle est mal nommée.
    Mais bon, je chipote 😁

  6. #6
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    5 011
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 5 011
    Par défaut
    Citation Envoyé par josmiley
    Je veux bien s'il s'agit de créer un vaisseau de façon interactive, le joueur choisi les caractéristiques par exemple, sinon je ne vois pas vraiment. La fonction retournera une instance de Vaisseau normalement, à moins qu'elle initialise en plus des variables plus globales, auquel cas elle est mal nommée.
    Mais bon, je chipote :mouais:
    Tu ne chipotes pas du tout, c'est même une excellente remarque d'architecture logicielle !

    En effet, utiliser une fonction externe comme cree_vaisseau() uniquement pour instancier un objet et lui assigner des attributs va à l'encontre des bonnes pratiques en Programmation Orientée Objet (POO). Le rôle de définir l'état initial d'un objet (comme son nom, ses armes, etc.) revient de droit à son constructeur, à savoir la méthode magique __init__.

    Plutôt que d'avoir une fonction qui fait ceci (d'ailleurs, profitons-en pour appliquer la norme PEP8 avec des variables et fonctions en minuscules) :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    def cree_vaisseau(nom, arme):
        vaisseau = Vaisseau()
        vaisseau.nom = nom
        vaisseau.armes = arme
        return vaisseau

    Il est beaucoup plus propre, clair et "Pythonique" d'intégrer cette logique directement à l'initialisation de la classe Vaisseau :

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Vaisseau:
        def __init__(self, nom, armes):
            self.nom = nom
            self.armes = armes
     
    # L'instanciation se fait alors naturellement, de manière bien plus concise :
    mon_vaisseau = Vaisseau("Faucon Millenium", "Lasers")

    Il n'y a finalement que quelques cas où une fonction de création séparée se justifie réellement :

    1. Le Design Pattern "Factory" (Fabrique) : Si la fonction implique une logique complexe pour déterminer quelle sous-classe instancier. Par exemple :

      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
       
      class Vaisseau:
          def __init__(self, nom):
              self.nom = nom
       
      class Chasseur(Vaisseau):
          pass
       
      class Croiseur(Vaisseau):
          pass
       
      def fabrique_vaisseau(nom, arme):
          # La fonction "masque" la logique complexe de création
          if arme == "Lasers lourds":
              return Croiseur(nom)
          return Chasseur(nom)
       
      # L'utilisateur ne se soucie pas de la classe exacte à instancier
      mon_vaisseau = fabrique_vaisseau("Faucon Millenium", "Lasers légers")
    2. L'interaction et les effets de bord : Comme tu le soulignes, si la fonction interagit avec le joueur via des inputs ou si elle modifie des états globaux en plus de la création (comme enregistrer le vaisseau nouvellement créé dans le gestionnaire global de la partie). Dans ce cas, cree_vaisseau gagne en effet à être renommée pour clarifier son rôle.


    Donc ta remarque tape dans le mille : si la fonction sert juste à construire l'objet de manière statique, c'est le constructeur de la classe qui doit s'en charger !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2013] Fonction Find qui ne trouve pas
    Par cdrouaud dans le forum Macros et VBA Excel
    Réponses: 19
    Dernier message: 26/07/2016, 18h57
  2. [PHP 5.0] Existe-il une fonction shuffle qui ne réinitialise pas les clés ?
    Par Dsphinx dans le forum Langage
    Réponses: 2
    Dernier message: 09/02/2012, 17h09
  3. une fonction supprime qui ne marche pas!
    Par hindou90 dans le forum C
    Réponses: 17
    Dernier message: 06/02/2010, 13h26
  4. Une fonction calcul qui ne calcule pas
    Par tranenengel dans le forum C
    Réponses: 3
    Dernier message: 18/06/2008, 13h11
  5. Une fonction settimeout qui s'execute pas
    Par stepon dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 03/08/2006, 12h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo