Lecture 15 Classes and Methods II

1. The 'init' method

The init method (short for “initialization”) is a special method that gets invoked when an object is instantiated. Its full name is __init__ (two underscore characters, followed by init, and then two more underscores). An init method for the Time class might look like this:
It is common for the parameters of __init__ to have the same names as the attributes. The statement: 'self.hour = hour' stores the value of the parameter hour as an attribute of self


The parameters are optional, so if you call Time with no arguments, you get the default values.


The script above didn't call the '__init__()' function but it was executed. Keep in mind that this initilization will be executed when you initilize an object to this class.

If you provide two arguments, they override hour and minute:


And of course, if you provide 3 arguments, they override all three default values:


2. One more example on this

The argument 'Jetty' in 'Student()' is passed to the 'something' parameter in the '__init__()' function.
'self' here represents the instance to be created by this class.



Does it matter if you have the argument inside the 'class Student():' declaration? Look at the following code:




I added an argument inside the 'class declaration' and I got the same results. In Python 3, you don't have to put any argument there.

3. The '__str__', '__repr__' method


__str__ is a special method, like __init__, that is supposed to return a string representation of an object.

When you print an object (sounds weird, right?), Python invokes the __str__ method:



The one above is interesting!! We didn't call the '__str__(self)' function, but the 'print(time)' function invokes it.

You must be curious about if you can directly call the __str__ method. The answer is YES.


__str__ is called when a user calls the print() function while __repr__ is called when a user just type the name of the instance:
When using the print() function in Python, the __str__ is called (if found) and otherwise, __repr__.



If I directly type the name of the instance in the Console, the '__repr__()' function will be called:



The id() fcuntion returns the location of the instance. The location is a representation of the real address. If you'd like to check the address of the instance, just comment the __str__ function and run the program:



4. The '__add__' method. (and Operator Overloading)

When we sum two objects in Python, this method is invoked. (Operator Overloading in Python)

When you apply the + operator to Time objects, Python invokes __add__. When you print the result, Python invokes __str__. So there is a lot happening behind the scenes!
This practice is called Operator Overloading because you’re overloading, or overwriting, how operators work. By “operator”, I mean symbols like +, -, and *.

Remember we overloaded __init__() to change how our classes initialized themselves? And we overrode __str__() to change how our class instances became strings? Well, we’re going to do the same thing with __add__ and some friends. This controls how instances add themselves together and with others.

Look at the following example:



Currently, that’s not going to work. Python is going to give me an error about "TypeError: unsupported operand type(s) for +: 'int' and 'Book'". That’s because our Book class has no idea what to do with a plus sign. Let’s fix that.



And of course, you can directly call it:



This concept applies to all these following operators:



It is confusing how the 'other' argument works there. It is actually taking all the attributes of 'duration' into 'other'. As shown below in our 'old' Time example:



5. Type-based dispatch
In the previous section we added two Time objects, but you also might want to add an integer to a Time object. The following is a version of __add__ that checks the type of other and invokes either add_time or increment:

Before we move forward, let's introduce the isinstance() function. The 'isinstance()' function returns True if the specified object is of the specified type, otherwise False. If the type parameter is a tuple, this function will return True if the object is one of the types in the tuple. Syntax

isinstance(object, type)

Check if the number 5 is an integer:



Example Check if "Hello" is one of the types described in the type parameter:



Example Check if y is an instance of myObj:



This following script works very well and more smart. The user can put a duration in the format of 'seconds', or 'hour:minute:second', the code can tell what is the data type and make corresponding calculation:





Tasks

1. According to the visible part of the code and the results, complete the code by replacing the boxes with your code.


2. Given the class 'Bag' as follows, instantiate an object called 'baggie'. Put string 'backpack' in 'baggie.data' using the 'add' function, and put two of 'packback' after this in the same list using the 'addtwice' function.


3. Create a class 'Box', use an '__init__' function to create the 'width' and the 'length' attributes of the class. Use a method (function) inside the class to return the area of the box.
After this class is created, instantiate an object called 'boxie', provide the width and the length parameters to this call to return the area of 'boxie'.

4. Complete the following code:


5. For example you are working for a bank. Design a class of 'Customer' which has several methods include: set up the initial balance, withdraw, and deposit money. Each operation of the customer should return the current balance. Now, here is a customer Jack tries to deposit $100 to the account and then withdraw $40. Instantiate the object Jack, return the current balance after these operations.

If the customer withdraw more than the current balance, the system should say something like 'Amount greater than available balance'.