Class Basics

A place where you can post Python-related tutorials you made yourself, or links to tutorials made by others.

Class Basics

Postby ichabod801 » Fri Feb 22, 2013 3:45 pm

Classes are the fundamental building block of the popular programming paradigm known as Object Oriented Programming (OOP). This is not a full tutorial on OOP, but rather just the basics of how to create and instantiate classes.

Classes are created with the syntax class <ClassName> (<ParentClass>):

Code: Select all
class Employee(object):


For now, don't worry about what the parent class is. That's a more advanced OOP topic called inheritance that another tutorial will cover. For now just use object as the parent class.

Note the colon at the end of the line. That means we are going to be starting an indented block of code, which will define the class. You can define variables in the class definition, but generally you just define functions. These functions are called the methods of the class. The most important method is __init__. The __init__ method is called when a new instance of the class is created.

Code: Select all
class Employee(object):
   """
   An employee at the ACME company.
   
   Attributes:
   first: The first name of the employee. (str)
   last: The last name of the employee. (str)
   position: The employee's job title. (str)
   staff: The employees supervised by this employee. (Employee)
   supervisor: The employee that supervises this employee. (Employee)
   """

   def __init__(self, first, last, position):
      """
      Employee.__init__(first, last, position) return None
      Set up the base attributes of the employee.
     
      Parameters:
      first: The first name of the employee. (str)
      last: The last name of the employee. (str)
      position: The employee's job title. (str)
      """
      self.first = first
      self.last = last
      self.position = position
      self.staff = []
      self.supervisor = None


Note that the first parameter of __init__ is self. The self paramter is the Employee instance in question at the time __init__ is processed. That class instance is a namespace. So the first line of __init__ (self.first = first) assigns the value of the first parameter to the first variable in the name space of the instance. Just as functions in a class are called methods, variables in a class or class isntance are called attributes. So what are these instances I keep talking about?

Code: Select all
>>> craig = Employee('Craig', "O'Brien", 'Mathematical Statistician')
>>> bob = Employee('Bob', 'Dobbs', 'Division Director')
>>> craig.first
'Craig'
>>> bob.first
'Bob'
>>> craig.position
'Mathematical Statistician'


In the above example, craig and bob are two instances of the Employee class. They are created by calling employee as a function. They both have the same attributes, but they have different values for those attributes. That is, they both have first names (the first attribute), but they have different first names.

You may have noticed that we defined four paramters for __init__, but only specified three when we used Employee as a function to create an instance. The self parameter is sort of an implied parameter that gets added to the list whenever a method of an instance is called.

Now we'll add some methods to our class:

Code: Select all
class Employee(object):
   """
   An employee at the ACME company.
   
   Attributes:
   first: The first name of the employee. (str)
   last: The last name of the employee. (str)
   position: The employee's job title. (str)
   staff: The employees supervised by this employee. (Employee)
   supervisor: The employee that supervises this employee. (Employee)
   """

   def __init__(self, first, last, position):
      """
      Employee.__init__(first, last, position) return None
      Set up the base attributes of the employee.
     
      Parameters:
      first: The first name of the employee. (str)
      last: The last name of the employee. (str)
      position: The employee's job title. (str)
      """
      self.first = first
      self.last = last
      self.position = position
      self.staff = []
      self.supervisor = None
     
   def alpha_name(self):
      """
      Employee.alpha_name() return str
      The employee's name for alphabetizing
      """
      return self.last + ', ' + self.first
     
   def full_name(self):
      """
      Employee.alpha_name() return str
      The employee's name for standard addressing
      """
      return self.first + ' ' + self.last
     
   def set_supervisor(self, supervisor):
      """
      Employee.set_supervisor() return None
      Set the employee's supervisor.
     
      Parameters:
      supervisor: The employee's new supervisor. (Employee)
      """
      self.supervisor = supervisor
      supervisor.staff.append(self)


The above code adds three methods: alpha_name, full_name, and set_supervisor. Note that none of those names start or end with two underscores like __init__. Those sort of names are reserved for special methods generally used in operator overloading, another advanced OOP topic to be covered in another tutorial. Also note that they all have the same first parameter of self, as __init__ did.

Also note that the new methods make use of that self parameter to access the attributes of the instance. The set_supervisor method also modifies an attribute of self, as well as an attribute of the supervisor parameter passed to it.

Code: Select all
>>> craig = Employee('Craig', "O'Brien", 'Mathematical Statistician')
>>> joe = Employee('Joe', 'Programmer', 'SAS Programmer')
>>> bob = Employee('Bob', 'Dobbs', 'Division Director')
>>> craig.alpha_name()
"O'Brien, Craig"
>>> craig.set_supervisor(bob)
>>> joe.set_supervisor(bob)
>>> craig.supervisor.full_name()
'Bob Dobbs'
>>> for employee in bob.staff: print(employee.full_name())
Craig O'Brien
Joe Programmer


Again, when we call the method of the craig instance (craig.alpha_name()), we don't pass the self parameter to the method call. With a normal function, this would give us an error: we defined one parameter but didn't pass any. Just remember that the self parameter is being taken care of behind the scenes: be sure you define it, and be sure not to pass it yourself.

So why did I go to all this trouble? I could have just made craig a dictionary:

Code: Select all
craig = {'first': 'Craig', 'last': "O'Brien", 'position': 'Mathematical Statistician'}


Then I could have made some functions that did the same thing as those methods, just pulling them out of the dictionaries. I could have even made an Employee function to create the dictionaries from parameters.

A lot of why we make classes has to do with some of the more advanced topics in OOP that I've mentioned. Inheritance allows you to easily create different types of employees, each with general attributes and methods needed for all employees and with special attributes and methods for the different types of employees. Operator overloading allows you make use of standard Python techniques with your classes. You could set up your Employee class os that when you sort a list of Employee instances, they automatically sort by alpha_name.

Furthermore it helps organize your code. Everything about employees is right there in one place when you (or the guy who has to deal with your program after you quit) need to find it. And Python will help you find it. dir(craig) will list all of the attributes and methods of that Employee instance. help(craig) will show the first block comment under the class definition, and help(craig.full_name) will show the block comment for that method.
Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, and C++
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801
 
Posts: 84
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

Re: Class Basics

Postby ichabod801 » Mon Mar 04, 2013 10:37 pm

Craig "Ichabod" O'Brien
Minimalist, buddhist, theist, and programmer
Current languages: Python, SAS, and C++
Previous serious languages: R, Java, VBA, Lisp, HyperTalk, BASIC
ichabod801
 
Posts: 84
Joined: Sat Feb 09, 2013 12:54 pm
Location: Outside Washington DC

Re: Class Basics

Postby micseydel » Tue Apr 02, 2013 8:00 am

I'd like to see more discussion about OOP rather than just describing how to use classes, and I think it would be helpful to make the magic less magical by including that
Code: Select all
instance.method(arg)

is equivalent to
Code: Select all
Class.method(instance, arg)

When I first saw that (and it wasn't in the original tutorial I found), I was like, "WHOA, that's what self means!"
Join the #python-forum IRC channel on irc.freenode.net!
User avatar
micseydel
 
Posts: 940
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

Re: Class Basics

Postby eightbits » Sun May 19, 2013 3:11 am

Code: Select all
  class Employee(object):


In the start of the tutorial I see the class defined as the above code.
I am using python 2.7.3 on Ubuntu 12.04
I have been starting to learn python and the examples I see usually have something like:
Code: Select all
class name:

Please forgive such an elementary topic but it seems confusing.
Thanks for any advice.

Note: I must not be using the code button, the code is not displayed as I think it should(?).
eightbits
 
Posts: 19
Joined: Sun May 19, 2013 2:42 am

Re: Class Basics

Postby stranac » Tue May 21, 2013 2:54 pm

The name in the parens is the parent class.

A blank class statement creates an old-style class, while subclassing object creates a new-style class.
New style classes provide a few advantages(and have no disadvantages I know of), so they're what you should always be using.
That's why you should always inherit from object(unless you're subclassing another new-style class).

All of the above is true for python 2.
In python 3, all classes are new-style by default, so subclassing object is not necessary.
Friendship is magic!

R.I.P. Tracy M. You will be missed.
User avatar
stranac
 
Posts: 909
Joined: Thu Feb 07, 2013 3:42 pm


Return to Tutorials

Who is online

Users browsing this forum: No registered users and 2 guests