Classes & Object Oriented Programming
Scope
● Object scope uses the 'instance-of' relationship: 1. First, look at the object itself (instance variable) 2. If the attribute is not found, look up the class of the object and search for the attribute in the class (class variable is shared by ALL objects in that class) 3. Look for inherited attributes from any parent classes.
instance variables
● self is used to create instance variables instead of local variables: def drive(self, distance): """ drive the car a given distance if it has enough fuel """ if distance > self.fuel: distance = self.fuel self.fuel = 0 else: self.fuel -= distance self.odometer += distance return distance ● Here, distance is a local variable since it's not self.distance, so it only exists in this function. ● self.fuel is an instance variable, available anywhere in the class ● instanc variables MUST be initialised somewhere in the code, i.e. in the CONSTRUCTOR for Car class
Built-In Class and Instance
Any of the built-in data structures in Python are defined as a class. Example: CONSTRUCTOR SHORTCUT list [ ] str " " dict { } tuple ( ) The constructor creates a new object, which is an instance of the class. When an instance is made of any of the built-in data structures, the new instance has a TYPE: the type of the class it was created from. These instances have internal attributes and associated methods that operate on those instances.
Calling a constructor
As mentioned, a constructor is called by using the name of the class as a function call (by adding () after the class name student = Student() ● creates a new instance using the constructor from class Student
CONSTRUCTOR
CLASS is the CONSTRUCTOR code that creates OBJECTS. CLASSES do not exist on their own; we ONLY use the INSTANCE (OBJECT) of the CLASS
Class & Instance
Class is a template for making a new OBJECT and that an object made by a class template is an INSTANCE of that class. The class template defines two major aspects of an instance: - the attributes contained in each instance - the operations that can be performed on each instance
Creating an 'instance'
Even though we have nothing in our class definition, MyClass has one important built-in ability: - the ability to make an 'instance' This is done by using the name of the class as a function: class MyClass (n.b. PascalCase) function MyClass()
'type' Function
Example: >>> my_list = [1, 2, 3] >>> type(my_list) <class 'list'> >>> my_dict = {1: 'a', 2: 'b', 3: 'c'] >>> type(my_dict) <class 'dict'> >>> my_list .sort(reverse=True) >>> my_list [3, 2, 1] >>> my_dict.values( ) ['a', 'b', 'c']
Variable vs Method
Examples: print(my_instance.my_val) ● Above prints a variable (my_val) associated with the object my_instance my_instance.my_method() N.B. parentheses ● Above calls a METHOD (my_method) associated with the objecy my_instance
Method vs. Function
Function is a small program or an encapsulation of an operation. It takes in parameters and (potentially) returns a value. Methods are functions that define the operations that can be done on an OBJECT. That is, methods are functions tied to a particular object.
Inheritance: "is-a" relationship
Inheritance is appropriate where you are building a more specialised version of a class. When class B inherits from class A, it should always be the case that an is-a relationship holds: (B "is an" A) For example, a Tree is a Plant, but it's not true to say a Cat is a Dog. So, it is appropriate for a Tree class to inherit from a Plant class, but not appropriate for a Cat class to inherit from a Dog class.
Nearly everything in Python is an OBJECT
Like the above, even a class is an OBJECT in Python.
Characteristics of OOP
Program structure: ● DATA stored as OBJECTS ● OBJECTS are INSTANCES of CLASSES ● CLASSES are BLUEPRINTS to create OBJECTS Program is built up by creating INSTANCES of CLASSES and these OBJECTS interact via 'messaging', i.e. calls to their METHODS Characteristics typically associated with OOP paradigm: ● Encapsulation - hiding the details to make the program clearer and more easily modified later. Data and functionality are located in the same place. Encapsulation binds together the data and functions the manipulate the data == CLASS e.g. my_string = "pixie" DATA my_string.upper() METHOD ● Polymorphism - allow one message to be sent to any object and have it respond appropriately based on the type of object it is. ● Inheritance - create a new OBJECT by inheriting many object characteristics while creating or over-riding for this OBJECT. ● Modularity - ability to make OBJECTS stand alone to that they can be re-used (MODULES). e.g. math module, random modules, libraries
Python
Python is an OOP language. Python uses CLASSES for ALL DATA TYPES. For example, we call a constructor such as 'list' or 'str' (or their shortcuts '[ ]' and " "), we are making a new object. These objects have attributes: - both lists and strings are collections with multiple elements These objects have methods: - sort a list by calling the method my_list.sort( ) - change a string to lowercase with the method my_string.lower( )
'dir' Function
This function lists all the attributes of the class. >>> class MyClass(): pass >>> dir(MyClass) '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__'] Most of the above attributes are provided, by default, by Python through the special object named 'object'. Even though we have NOT provided any attributes to MyClass, it has a set of methods that begin with the double underscore(_ _), such as __init__ . Thes have a predefined meaning to Python.
Object Oriented Programming
Views a program as a set of objects which have two characteristics: - each object has some attributes stored within the object, i.e what does it know about itself - the object responds to methods (what does it do) where each object can interact with other objects to accomplish tasks. N.B. Methods are also attributes that are particular to that kind of OBJECT.
General rule: Define all of your class's fields in the __init__ function
def __init__(self, fuel=0): """ initialise a Car""" self.fuel = fuel self.odometer = 0
Class definition
keyword 'class' + class name in PascalCase + ( ): as above: >>> class MyClass(): pass Following the colon is a suite of code (variable assignments or methods) that defines the class. N.B. We use keyword 'pass' to indicate that the suite is empty at present. It is an indication of intent.
Class & Objects
● A class is a blueprint (the code) for creating an object ● A class is a new type ● Objects store data in instance variables and provide access to the methods (functions) defined in the class A CLASS is built out of: - Variables, Functions & Statements DATA = Variables BEHAVIOURS = Functions + Statements DATA + BEHAVIOURS = CLASS
Naming conventions
● Class names begin with a capital and use PascalCase, e.g. StudentRecord ● Method names follow same convention as function names: get_value N.B. Function naming ∈ VERB PHRASES Check by using the phrase: "This function will.... get_value is_valid (Boolean) ● Constant names are UPPERCASE ● Variable names begin with lower case and use the underscore convention, e.g. my_name
Python Standard Method: CONSTRUCTOR
● Constructor is called when an instance is made ● Format: def __init__ (self): ... ● Usually the first method in a class definition ● Usually initialises the object's data attributes ● by assigning values in the constructor, every instance will start out with the same variables
'instance-of' relationship
● Every instance has as its type the class that it was made from, an instance rembers its CLASS ● This called the 'instance-of' relationship ● stored in the __class__ attribute of the instance
__str__ for printing
● Format: def __str__(self): # print "In __str__ method" return "{} {}, ID:{}".format(self.first_name, self.last_name, self.id) ● __str__ never takes a parameter other than self ● When print(my_inst)called, it is assumed by Python to be a call to "convert the instance to a string", which is the __str__ method ● In the method, my_inst is bound to self, and printing then occurs using that instance. ● __str__ must return a string! N.B. If you use print, it returns NONE and dose not print!! >>> def __str__(self): print"{} {}, ID:{}".format(self.first_name, self.last_name, self.id)) >>> None
The 'dot' notation
● We can refer to the ATTRIBUTES of an OBJECT by using a DOT reference, of the form: object.attribute ● Whatever is on the RIGHT of the DOT is a member of wahtever is on the LEFT ● The ATTRIBUTE can be a variable or a function ● It is part of the OBJECT, either directly or by that object being part of a CLASS Consider a string and the string's 'count' method: - the count method takes a single argument, a string, and counts the number of occurrences of the argument string in the calling string. Example: >>> a_str = "hi mom" >>> print a_str.count("m") 2 >>> print a_str.count <built-in method count of str object at 0xcb0f20> This notation works because a method is just another attribute of an OBJECT. 2
Methods & 'self'
● methods are defined inside the suite of a class ● methods always bind the first parameter in the definition to the object that called it ● This parameter can be named anything, but traditionally is named 'self' class MyClass(object): def my_method(self, param1): suite ● self is an important variable. In any method it is bound to the object that called the method ● through self we can access the instance that called the method (and all of its attributes as a result) ● when a dot method call is made, the object that called the method is automatically assigned to self ● we can use self to remember, and therefore refer, to the calling object ● to reference any part of the calling object, we must always precede it with self.