154

I'm trying to learn python and I now I am trying to get the hang of classes and how to manipulate them with instances.

I can't seem to understand this practice problem:

Create and return a student object whose name, age, and major are the same as those given as input

def make_student(name, age, major)

I just don't get what it means by object, do they mean I should create an array inside the function that holds these values? or create a class and let this function be inside it, and assign instances? (before this question i was asked to set up a student class with name, age, and major inside)

class Student:
    name = "Unknown name"
    age = 0
    major = "Unknown major"
Mohsen M. Alrasheed
  • 1,551
  • 2
  • 10
  • 4
  • Read the data model docs, specifically the `__init__` method is relevant here: http://docs.python.org/2/reference/datamodel.html#object.__init__ – wim Feb 26 '13 at 04:51
  • 2
    None (no quotes) is the common *unassigned* default value in python – monkut Feb 26 '13 at 05:00

4 Answers4

191
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

Note that even though one of the principles in Python's philosophy is "there should be one—and preferably only one—obvious way to do it", there are still multiple ways to do this. You can also use the two following snippets of code to take advantage of Python's dynamic capabilities:

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

I prefer the former, but there are instances where the latter can be useful – one being when working with document databases like MongoDB.

Darlesson
  • 5,742
  • 2
  • 21
  • 26
Wulfram
  • 3,292
  • 2
  • 15
  • 11
  • 19
    why are you initializing them as class variables prior to your init? (curious; haven't seen that pattern very often) – GoingTharn Sep 21 '13 at 01:25
  • 7
    For readability purposes. By putting the class variables near the top prior to the init, I can quickly see which variables are in the class scope since they might not all be set by the constructor. – Wulfram Nov 08 '13 at 00:00
  • 1
    Here the name of the object which is the instance of the class Student is going to remain student right? What if I want multiple objects at each call with the name student01, student02,.. and so on? – Yathi Jun 18 '14 at 05:21
  • 12
    Creating class variables to see what your instance variables is terrible practice. To any novice readers: look at @pyrospade's answer instead. – anon01 Mar 26 '18 at 23:40
  • 2
    Your example is misleading. Please use class variable names which are in reality a property of all students, rather than misusing a property of each student. For example: use `class Unicorn` and `has_hooves = True` instead of `name = ""`. – Tim Kuipers Aug 15 '18 at 13:08
58

Create a class and give it an __init__ method:

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

Now, you can initialize an instance of the Student class:

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

Although I'm not sure why you need a make_student student function if it does the same thing as Student.__init__.

Blender
  • 289,723
  • 53
  • 439
  • 496
  • 1
    Our teacher gave us a test.py program that tests if we did the problems correctly. The question wants me to specifically to use the make_student function. The end goal is to: s1 = make_student(name, age, major) and now I have everything assigned to s1. But again I'm not sure what they want s1 to be? I can do this with an array {'name' : name..etc} but that didn't give me a correct answer so I'm assuming I need to implement what I learned from classes and instances – Mohsen M. Alrasheed Feb 26 '13 at 05:03
  • 1
    The so called "factory method" pattern, the one where you use a method or a function to create object of some kind instead of creating them directly in the code, is a useful pattern, it allows you to exploit nice things about inheritance for example. Look it up ;) – bracco23 Nov 01 '16 at 20:34
33

Objects are instances of classes. Classes are just the blueprints for objects. So given your class definition -

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

You can create a make_student function by explicitly assigning the attributes to a new instance of Student -

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

But it probably makes more sense to do this in a 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

The constructor is called when you use Student(). It will take the arguments defined in the __init__ method. The constructor signature would now essentially be Student(name, age, major).

If you use that, then a make_student function is trivial (and superfluous) -

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

For fun, here is an example of how to create a make_student function without defining a class. Please do not try this at home.

def make_student(name, age, major):
    return type('Student', (object,),
                {'name': name, 'age': age, 'major': major})()
pyrospade
  • 7,870
  • 4
  • 36
  • 52
  • Actually, I prefer not to do class Name(object): for verbosity reasons. The Python documentation tends to not do it as well. I like the "dangerous" example of feeding in a dict though. http://docs.python.org/2/tutorial/classes.html – Wulfram Feb 26 '13 at 05:07
  • 3
    I withdraw my previous comment. See http://stackoverflow.com/questions/4015417/python-class-inherits-object. So there is actually a reason to spell out class Name(object): – Wulfram Feb 26 '13 at 05:12
  • 2
    There is no constructor in python :) – BigSack Jan 13 '14 at 09:04
  • 1
    How is the `__init__()` method different from a constructor? – pyrospade Jan 13 '14 at 13:55
  • 1
    `__init__` is not a constructor, "because the object has already been constructed by the time `__init__` is called, and you already have a valid reference to the new instance of the class." (http://www.diveintopython.net/object_oriented_framework/defining_classes.html) – Brian Z Apr 25 '15 at 13:04
  • 1
    I guess that is technically correct since `__new__` is the real constructor; however, `__init__` is used analogously as constructors are used in other languages (e.g. C++, Java). – pyrospade Apr 25 '15 at 18:42
  • 1
    what's the purpose of putting 'object' when creating a new class? – user97662 Jul 11 '16 at 03:27
  • 1
    To create a new-style class - http://stackoverflow.com/questions/15374857/should-all-python-classes-extend-object – pyrospade Jul 11 '16 at 07:00
3

when you create an object using predefine class, at first you want to create a variable for storing that object. Then you can create object and store variable that you created.

class Student:
     def __init__(self):

# creating an object....

   student1=Student()

Actually this init method is the constructor of class.you can initialize that method using some attributes.. In that point , when you creating an object , you will have to pass some values for particular attributes..

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

 # creating an object.......

     student2=Student("smith",25)
Gayan Sampath
  • 163
  • 2
  • 5