Python, création d'objets

132

J'essaie d'apprendre le python et j'essaye maintenant de comprendre les classes et comment les manipuler avec des instances.

Je n'arrive pas à comprendre ce problème de pratique:

Créer et renvoyer un objet étudiant dont le nom, l'âge et la majeure sont les mêmes que ceux donnés en entrée

def make_student(name, age, major)

Je ne comprends tout simplement pas ce que cela signifie par objet, cela signifie-t-il que je devrais créer un tableau à l'intérieur de la fonction qui contient ces valeurs? ou créer une classe et laisser cette fonction être à l'intérieur, et attribuer des instances? (avant cette question, on m'a demandé de créer une classe d'étudiants avec le nom, l'âge et la majeure à l'intérieur)

class Student:
    name = "Unknown name"
    age = 0
    major = "Unknown major"
Mohsen M. Alrasheed
la source
Lisez la documentation sur le modèle de données, en particulier la __init__méthode est pertinente ici: docs.python.org/2/reference/datamodel.html#object.__init__
wim
1
Aucun (pas de guillemets) est la valeur par défaut commune non attribuée en python
monkut

Réponses:

173
class Student(object):
    name = ""
    age = 0
    major = ""

    # The class "constructor" - It's actually an initializer 
    def __init__(self, name, age, major):
        self.name = name
        self.age = age
        self.major = major

def make_student(name, age, major):
    student = Student(name, age, major)
    return student

Notez que même si l'un des principes de la philosophie de Python est "il devrait y avoir une - et de préférence une seule - façon évidente de le faire" , il existe encore plusieurs façons de le faire. Vous pouvez également utiliser les deux extraits de code suivants pour tirer parti des capacités dynamiques de Python:

class Student(object):
    name = ""
    age = 0
    major = ""

def make_student(name, age, major):
    student = Student()
    student.name = name
    student.age = age
    student.major = major
    # Note: I didn't need to create a variable in the class definition before doing this.
    student.gpa = float(4.0)
    return student

Je préfère le premier, mais il y a des cas où le second peut être utile - l'un étant lorsque vous travaillez avec des bases de données de documents comme MongoDB.

Wulfram
la source
17
pourquoi les initialisez-vous en tant que variables de classe avant votre init? (curieux; je n'ai pas vu ce modèle très souvent)
GoingTharn
7
À des fins de lisibilité. En plaçant les variables de classe vers le haut avant l'initialisation, je peux rapidement voir quelles variables sont dans la portée de la classe car elles peuvent ne pas être toutes définies par le constructeur.
Wulfram
1
Ici, le nom de l'objet qui est l'instance de la classe Student va rester étudiant, non? Que faire si je veux plusieurs objets à chaque appel avec le nom student01, student02, .. et ainsi de suite?
Yathi
9
Créer des variables de classe pour voir quelles sont vos variables d'instance est une mauvaise pratique. À tous les lecteurs novices: regardez plutôt la réponse de @ pyrospade.
anon01
2
Votre exemple est trompeur. Veuillez utiliser des noms de variables de classe qui sont en réalité une propriété de tous les élèves, plutôt que de mal utiliser une propriété de chaque élève. Par exemple: utilisez class Unicornet has_hooves = Trueau lieu de name = "".
Tim Kuipers
49

Créez une classe et donnez-lui une __init__méthode:

class Student:
    def __init__(self, name, age, major):
        self.name = name
        self.age = age
        self.major = major

    def is_old(self):
        return self.age > 100

Maintenant, vous pouvez initialiser une instance de la Studentclasse:

>>> s = Student('John', 88, None)
>>> s.name
    'John'
>>> s.age
    88

Bien que je ne sache pas pourquoi vous avez besoin d'une make_studentfonction d'étudiant si elle fait la même chose que Student.__init__.

Mixeur
la source
Notre professeur nous a donné un programme test.py qui teste si nous avons correctement résolu les problèmes. La question veut que j'utilise spécifiquement la fonction make_student. Le but final est de: s1 = make_student (nom, âge, majeur) et maintenant j'ai tout assigné à s1. Mais encore une fois, je ne suis pas sûr de ce qu'ils veulent que s1 soit? Je peux le faire avec un tableau {'name': name..etc} mais cela ne m'a pas donné de réponse correcte, donc je suppose que je dois implémenter ce que j'ai appris des classes et des instances
Mohsen M. Alrasheed
1
Le modèle dit de "méthode d'usine", celui où vous utilisez une méthode ou une fonction pour créer un objet quelconque au lieu de les créer directement dans le code, est un modèle utile, il vous permet d'exploiter de belles choses sur l'héritage par exemple . Cherchez-le;)
bracco23
28

Les objets sont des instances de classes. Les classes ne sont que les plans des objets. Donc, étant donné votre définition de classe -

# Note the added (object) - this is the preferred way of creating new classes
class Student(object):
    name = "Unknown name"
    age = 0
    major = "Unknown major"

Vous pouvez créer une make_studentfonction en attribuant explicitement les attributs à une nouvelle instance de Student-

def make_student(name, age, major):
    student = Student()
    student.name = name
    student.age = age
    student.major = major
    return student

Mais il est probablement plus logique de le faire dans un constructeur ( __init__) -

class Student(object):
    def __init__(self, name="Unknown name", age=0, major="Unknown major"):
        self.name = name
        self.age = age
        self.major = major

Le constructeur est appelé lorsque vous utilisez Student(). Il prendra les arguments définis dans la __init__méthode. La signature du constructeur serait désormais essentiellement Student(name, age, major).

Si vous utilisez cela, alors une make_studentfonction est triviale (et superflue) -

def make_student(name, age, major):
    return Student(name, age, major)

Pour le plaisir, voici un exemple de création d'une make_studentfonction sans définir de classe. Veuillez ne pas essayer cela à la maison.

def make_student(name, age, major):
    return type('Student', (object,),
                {'name': name, 'age': age, 'major': major})()
pyrospade
la source
En fait, je préfère ne pas faire de classe Nom (objet): pour des raisons de verbosité. La documentation Python a tendance à ne pas le faire aussi. J'aime bien l'exemple "dangereux" de nourrir un dict. docs.python.org/2/tutorial/classes.html
Wulfram
1
Je retire mon commentaire précédent. Voir stackoverflow.com/questions/4015417/… . Il y a donc en fait une raison pour épeler le nom de la classe (objet):
Wulfram
1
Il n'y a pas de constructeur en python :)
BigSack
En quoi la __init__()méthode est-elle différente d'un constructeur?
pyrospade
1
__init__n'est pas un constructeur, "parce que l'objet a déjà été construit au moment de l' __init__appel et que vous avez déjà une référence valide à la nouvelle instance de la classe." ( diveintopython.net/object_oriented_framework/… )
Brian Z
3

lorsque vous créez un objet à l'aide de la classe predefine, vous voulez d'abord créer une variable pour stocker cet objet. Ensuite, vous pouvez créer un objet et stocker la variable que vous avez créée.

class Student:
     def __init__(self):

# creating an object....

   student1=Student()

En fait, cette méthode init est le constructeur de la classe. Vous pouvez initialiser cette méthode à l'aide de certains attributs. À ce stade, lorsque vous créez un objet, vous devrez passer des valeurs pour des attributs particuliers.

class Student:
      def __init__(self,name,age):
            self.name=value
            self.age=value

 # creating an object.......

     student2=Student("smith",25)
GT_hash
la source