Lecture 16 Class and Objects

1. Introduction

Having used some of Python’s built-in types, we are ready to create a userdefined type: the Point.

An alternative is to define a new user-defined compound type, also called a class. This approach involves a bit more effort, but it has advantages that will be apparent soon. A class definition looks like this:

Class definitions can appear anywhere in a program, but they are usually near the beginning (after the import statements). The syntax rules for a class definition are the same as for other compound statements

This definition creates a new class called Point. The pass statement has no effect; it is only necessary because a compound statement must have something in its body. By creating the Point class, we created a new type, also called Point. The members of this type are called instances of the type or objects. Creating a new instance is called instantiation. To instantiate a Point object, we call a function named (you guessed it) Point

The variable blank is assigned a reference to a new Point object. A function like Point that creates new objects is called a constructor.

Here a pretty good chart to show you the relationshipo between an object and the class:


2. Attributes
We can add new data to an instance using dot notation:


This syntax is similar to the syntax for selecting a variable from a module, such as math.pi or string.uppercase. In this case, though, we are selecting a data item from an instance. These named items are called attributes.

The following state diagram shows the result of these assignments:

The variable blank refers to a Point object, which contains two attributes. Each attribute refers to a floating-point number.
The expression blank.x means, "Go to the object blank refers to and get the value of x." In this case, we assign that value to a variable named x. There
is no conflict between the variable x and the attribute x. The purpose of dot notation is to identify which variable you are referring to unambiguously.

3. Sameness
The meaning of the word \same" seems perfectly clear until you give it some thought, and then you realize there is more to it than you expected. For example, if you say, \Chris and I have the same car," you mean that his car and yours are the same make and model, but that they are two different cars.

If you say, \Chris and I have the same mother," you mean that his mother and yours are the same person.1 So the idea of \sameness" is different depending on the context. When you talk about objects, there is a similar ambiguity. For example, if two Points are the same, does that mean they contain the same data (coordinates) or that they are actually the same object? To find out if two references refer to the same object, use the == operator. For example:


Even though p1 and p2 contain the same coordinates, they are not the same object. If we assign p1 to p2, then the two variables are aliases of the same object:



However, if you can make a function to compare the concents of two objects.


4. Rectangles
For example, a new 'Rectangle' class can be created.
To instantiate the object by 'box = Rectangle()', 'box.corner = Point()'.

This new object is instatiated by the class.

This code creates a new Rectangle object with two floating-point attributes. To specify the upper-left corner, we can embed an object within an object

The dot operator composes. The expression box.corner.x means, \Go to the object box refers to and select the attribute named corner; then go to that object and select the attribute named x."
The figure shows the state of this object:


5. Objects are mutable
We can change the state of an object by making an assignment to one of its attributes. For example, to change the size of a rectangle without changing its position, we could modify the values of width and height:

We could encapsulate this code in a method and generalize it to grow the rectangle by any amount



6. Copying
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other. This module provides generic shallow and deep copy operations (explained below).

Interface summary:
copy.copy(x) Return a shallow copy of x.
copy.deepcopy(x[, memo]) Return a deep copy of x.

A shallow copy constructs a new compound object and then (to the extent possible) inserts references into it to the objects found in the original. A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

Once we import the copy module, we can use the copy method to make a new Point. p1 and p2 are not the same point, but they contain the same data.

To copy a simple object like a Point, which doesn’t contain any embedded objects, copy is sufficient. This is called shallow copying. For something like a Rectangle, which contains a reference to a Point, copy doesn’t do quite the right thing. It copies the reference to the Point object, so both the old Rectangle and the new one refer to a single Point. If we create a box, b1, in the usual way and then make a copy, b2, using copy, the resulting state diagram looks like this:



This is almost certainly not what we want. In this case, invoking growRect on one of the Rectangles would not affect the other, but invoking moveRect on either would affect both! This behavior is confusing and error-prone. Fortunately, the copy module contains a method named deepcopy that copies not only the object but also any embedded objects. You will not be surprised to learn that this operation is called a deep copy.





Tasks:

1. Creat a class called 'box'. Create a new instance from class 'box' called 'square', add attributes of 'width' and 'length' to 'square'. Create a function called 'area' to take the information of the instance 'square' and calculate/return the acrea of this shape.

2. Explain the differences of instantiating the 'square' object outside and inside the 'area' function.

3. There is a dictionary called 'height': {'Tom': '5', 'Jim': '6', 'Jimmy': '6.2', 'Tommy': '7'}, and another dictionary called 'salary': {'Tom': '5000', 'Jim': '6000', 'Jimmy': '6200', 'Tommy': '7000'}. Create a class called 'People', instantiate these four people in the dictionary using this 'People' class. Use a function to find the tallest person in these four people. Use another function to find whose salary is '6000'. Print this out: XXX is the tallest person and XXX's income is 6000.