Merged the branches.
authorShantanu <shantanu@fossee.in>
Thu, 10 Jun 2010 18:54:04 +0530
changeset 97 597ee2fcb795
parent 96 bb52cf47e920 (current diff)
parent 89 449760bc4089 (diff)
child 98 678c7c01b5d5
Merged the branches.
--- a/basic_python/oop.rst	Thu Jun 10 18:53:49 2010 +0530
+++ b/basic_python/oop.rst	Thu Jun 10 18:54:04 2010 +0530
@@ -3,7 +3,7 @@
 
 In the previous sections we learnt about functions which provide certain level
 of abstraction to our code by holding the code which performs one or more
-specific functionalities. We were able to use this function as many times as we
+specific functionality. We were able to use this function as many times as we
 wanted. In addition to functions, Python also higher level of abstractions
 through *Classes* and *Objects*. *Objects* can be loosely defined as a
 collection of a set of data items and a set of methods. The data items can be
@@ -31,7 +31,7 @@
 which it was called as the first argument. It is conventionally given the name,
 *self*. Note that *self* is only a convention. You can use any other name, but
 the first argument to the method will always be the same object of the class
-from which the method was called. The data memebers that belong to the class are
+from which the method was called. The data members that belong to the class are
 called as *class attributes*. *Class attributes* are preceded by the object of
 the class and a dot. In the above example, *name* is a class attribute since it
 is preceded by the *self* object. *Class attributes* can be accessed from
@@ -70,3 +70,45 @@
       print e.name
   AttributeError: Employee instance has no attribute 'name'
 
+It is also possible to assign values to the attributes using the above notation::
+
+  >>> emp = Employee()
+  >>> emp.name = 'John'
+  >>> print emp.name
+  John
+
+Magic methods
+-------------
+
+Python reserves a number of names starting and ending with **__**. Note that it
+is a double underscore. We must not invent names of this kind in our programs.
+These methods are generally referred to as *Magic methods* or sometimes called
+as *Special Methods*. Each *Magic method* performs a specific function. One such
+magic method we will discuss now is **__init__** method. If you are from C++
+background, the **__init__** method is analogous to the class constructor. This
+method is called a constructor because, it is implicitly called everytime a new
+instance of the class is created. So effectively **__init__** method constructs
+the object from the class and sets up some initial values for the object. Other
+than the above special properties, the **__init__** method is similar to any other
+class method. The argument passing rules are same for **__init__** method. Although,
+since **__init__** is called when the object is created we need to pass the
+arguments to the class name we call while creating the object. It passes the
+arguments to the **__init__** method::
+
+  class Employee:
+    def __init__(self, name):
+      self.name = name
+
+    def getName(self):
+      return self.name
+
+  >>> emp = Employee('John')
+  >>> print emp.getName()
+  John
+
+
+Writing Object Oriented Code
+----------------------------
+
+Object oriented code mainly encompasses three components: Encapsulation, Inheritence and Polymorphism.
+Lets briefly look at each of them with examples.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tdd/tdd.rst	Thu Jun 10 18:54:04 2010 +0530
@@ -0,0 +1,78 @@
+Fundamentals
+============
+
+Test Driven Development, abbreviated as TDD is a method of software
+development which banks on the idea of writing test cases that fail for the
+code that doesn't even exist yet. The actual code is written later to pass
+the test and then refactored.
+
+Writing tests
+=============
+
+Writing a test is simple. Writing a failing test? It is much more simple.
+Let us consider a very simple program which returns the Greatest Common
+Divisor (GCD) of two numbers. Since the test cases for the code is written
+prior to the code itself, it is necessary to have a clear idea of the code
+units that our program will contain. Let us attempt to clearly define the
+code units in our case of a GCD program. Let our program contain one and
+only one function called gcd() which takes in two arguments as parameters.
+These arguments are the numbers for which GCD must be computed. The gcd()
+function returns a single value which is the GCD of the two arguments
+passed. So if we want to find out GCD of 44, 23, I will call my code unit
+as c = gcd(44, 23) where c will contain the GCD of those two numbers.
+
+Now we have defined our code units, how will we write tests? Before writing
+the test, a very fundamental question arises in our minds. How do tests
+look like? So let us answer this question first. Tests are nothing but a
+series of assertions which are either True or False depending on the
+expected behaviour of the code. We tell our tests whether our code unit
+asserts True or asserts False based on the expected behaviour of the code
+units. If we happen to run the tests now we are sure to get errors. Oh! But
+why? We don't even have the function gcd to call. The test code doesn't
+even compile! So what should we do now? So the idea is to first write the
+stubs for the code units before we start writing tests. This is necessary
+for two reasons. Firstly, by writing the stubs for the code units we will
+be able to correctly decide and fix on to the code units that we have
+planned to include in our program. We have a clear cut idea as to how our
+program is structured, how the tests must be written among other
+things. Secondly, the tests must at least compile and then fail! If the
+tests don't even compile, that doesn't mean the tests failed. It means
+it was a failure on the programmer's part. Let us define our stub::
+
+  def gcd(a, b):
+      pass
+
+This stub does nothing other than defining a new function called gcd which
+takes two parameters a and b for which the GCD must be calculated. The body
+of the function just contains pass which means it does nothing, i.e. empty.
+We have our stub ready. One important thing we need to keep in mind when
+we adopt TDD methodology is that we need to have a clear set of results
+defined for our code units. To put it more clearly, for every given set of
+inputs as test case we must have, before hand, the exact outputs that are
+expected for those input test cases. If we don't have that we have failed
+in the first step of the TDD methodology itself. We must never run for
+outputs for our test cases after we have the code ready or even while
+writing tests. The expected outputs/behaviour must be in our hands before
+we start writing tests. Therefore let us define our test cases and the
+expected output for those inputs. Let one of our test cases be 48 and 64
+as *a* and *b* respectively. For this test case we know that the GCD is
+16. So that is the expected output. Let our second test case be 44 and
+19 as *a* and *b* respectively. We know that their GCD is 1 by simple paper
+and pen calculation.
+
+Now we know what a test is? What are the ingredients required to write
+tests? So what else should we wait for? Let us write our first test!::
+
+  tc1 = gcd(48, 64)
+  if tc1 != 16:
+      print "Test failed for the case a=48 and b=64. Expected 16. Obtained
+          %d instead." % tc1
+      exit(1)
+  
+  tc2 = gcd(44, 19)
+  if tc2 != 1:
+      print "Test failed for the case a=44 and b=19. Expected 1. Obtained
+          %d instead." % tc2
+      exit(1)
+
+  print "All tests passed!"