Python, creando objetos

132

Estoy tratando de aprender Python y ahora estoy tratando de acostumbrarme a las clases y cómo manipularlas con instancias.

Parece que no puedo entender este problema de práctica:

Cree y devuelva un objeto de estudiante cuyo nombre, edad y especialización sean los mismos que los proporcionados como entrada.

def make_student(name, age, major)

Simplemente no entiendo lo que significa por objeto, ¿significan que debería crear una matriz dentro de la función que contiene estos valores? o crear una clase y dejar que esta función esté dentro de ella, y asignar instancias? (antes de esta pregunta, me pidieron que organizara una clase de estudiante con nombre, edad y especialización dentro)

class Student:
    name = "Unknown name"
    age = 0
    major = "Unknown major"
Mohsen M. Alrasheed
fuente
Lea los documentos del modelo de datos, específicamente el __init__método es relevante aquí: docs.python.org/2/reference/datamodel.html#object.__init__
wim
1
Ninguno (sin comillas) es el valor predeterminado común no asignado en python
monkut

Respuestas:

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

Tenga en cuenta que aunque uno de los principios en la filosofía de Python es "debería haber una, y preferiblemente solo una, forma obvia de hacerlo" , todavía hay múltiples formas de hacerlo. También puede usar los dos fragmentos de código siguientes para aprovechar las capacidades dinámicas 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

Prefiero el primero, pero hay casos en que el último puede ser útil, uno de ellos cuando se trabaja con bases de datos de documentos como MongoDB.

Wulfram
fuente
17
¿Por qué las inicializas como variables de clase antes de tu inicio? (curioso; no he visto ese patrón muy a menudo)
GoingTharn
77
Para fines de legibilidad. Al colocar las variables de clase cerca de la parte superior antes del inicio, puedo ver rápidamente qué variables están en el alcance de la clase, ya que es posible que el constructor no las configure todas.
Wulfram
1
Aquí el nombre del objeto que es la instancia de la clase Estudiante seguirá siendo estudiante ¿verdad? ¿Qué sucede si quiero varios objetos en cada llamada con el nombre student01, student02, ... y así sucesivamente?
Yathi
9
Crear variables de clase para ver cuáles son las variables de su instancia es una práctica terrible. Para cualquier lector novato: mire la respuesta de @ pyrospade en su lugar.
anon01
2
Tu ejemplo es engañoso. Utilice los nombres de las variables de clase que en realidad son propiedad de todos los alumnos, en lugar de utilizar indebidamente una propiedad de cada alumno. Por ejemplo: use class Unicorny en has_hooves = Truelugar de name = "".
Tim Kuipers
49

Crea una clase y dale un __init__método:

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

Ahora, puede inicializar una instancia de la Studentclase:

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

Aunque no estoy seguro de por qué necesita una make_studentfunción de estudiante si hace lo mismo que Student.__init__.

Licuadora
fuente
Nuestro maestro nos dio un programa test.py que evalúa si resolvimos los problemas correctamente. La pregunta quiere que use específicamente la función make_student. El objetivo final es: s1 = make_student (nombre, edad, especialidad) y ahora tengo todo asignado a s1. Pero, de nuevo, no estoy seguro de qué quieren que sea Puedo hacer esto con una matriz {'name': name..etc} pero eso no me dio una respuesta correcta, así que supongo que necesito implementar lo que aprendí de las clases y las instancias
Mohsen M. Alrasheed
1
El llamado patrón de "método de fábrica", aquel en el que utiliza un método o una función para crear objetos de algún tipo en lugar de crearlos directamente en el código, es un patrón útil, le permite explotar cosas bonitas sobre la herencia, por ejemplo .
Búscalo
28

Los objetos son instancias de clases. Las clases son solo los planos de los objetos. Entonces, dada su definición de clase,

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

Puede crear una make_studentfunción asignando explícitamente los atributos a una nueva instancia de Student-

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

Pero probablemente tenga más sentido hacer esto en un constructor ( __init__) -

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

Se llama al constructor cuando lo usa Student(). Tomará los argumentos definidos en el __init__método. La firma del constructor ahora sería esencialmente Student(name, age, major).

Si usa eso, entonces una make_studentfunción es trivial (y superflua):

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

Por diversión, aquí hay un ejemplo de cómo crear una make_studentfunción sin definir una clase. Por favor, no intente esto en casa.

def make_student(name, age, major):
    return type('Student', (object,),
                {'name': name, 'age': age, 'major': major})()
pyrospade
fuente
En realidad, prefiero no hacer la clase Nombre (objeto): por razones de verbosidad. La documentación de Python tiende a no hacerlo también. Sin embargo, me gusta el ejemplo "peligroso" de alimentar en un dict. docs.python.org/2/tutorial/classes.html
Wulfram
1
Retiro mi comentario anterior. Ver stackoverflow.com/questions/4015417/… . Entonces, en realidad hay una razón para deletrear el Nombre de la clase (objeto):
Wulfram
1
No hay constructor en python :)
BigSack
¿Cómo es el __init__()método diferente de un constructor?
pyrospade
1
__init__no es un constructor, "porque el objeto ya se construyó cuando __init__se llama y ya tiene una referencia válida a la nueva instancia de la clase". ( diveintopython.net/object_oriented_framework/… )
Brian Z
3

cuando crea un objeto usando una clase predefinida, al principio desea crear una variable para almacenar ese objeto. Luego puede crear objetos y almacenar variables que haya creado.

class Student:
     def __init__(self):

# creating an object....

   student1=Student()

En realidad, este método init es el constructor de la clase. Puede inicializar ese método usando algunos atributos. En ese punto, cuando cree un objeto, tendrá que pasar algunos valores para atributos particulares.

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

 # creating an object.......

     student2=Student("smith",25)
GT_hash
fuente