S206E057 – Spring 2016 S206E057 -- Lecture 21, 5/26/2016, Python – classes Copyright ©2016, Chiu-Shui Chan. All Rights Reserved. Python has the notions of classes and objects from using dictionaries and modules to facilitate repetitious tasks. Information about the definition of modules, classes, and objects could be found online and manuals. Materials provided in this lecture are compiled partially from the following page: http://learnpythonthehardway.org/book/ex40.html. Major applications of modules and classes are to set up some definitions of variables for a design routine, then save them and used by or in other design projects. Here are brief explanations of these concepts. Modules are like dictionaries. A module is a Python file that (generally) has only definitions of variables, functions, and classes. Notions of constructing modules to make dictionaries have the following sequences. 1. You write a Python file with some functions or variables in it. 2. You import that file to a file in use. 3. And you can access the functions or variables in that module with the . (dot) operator. Exercise one: coding of a module example Following these notions, here is an example of module in Python. I have a module named mystuff.py, which will make a print (of A), define a function of “apple”, a variable of tangerine, print the tangerine variable (of B) and call the apple function to print (C). The image on the right shows the code in it and the results of execution line after line. Once these codes are written and saved as mystuff.py module, we can use this mystuff module with the built-in function of import from another file of callmystuff.py to access the apple function and the variable of tangerine in mystuff.py file. The codes of the “callmystuff.py” and its run results are shown on the lower right image. import mystuff mystuff.apple() In this call file example, when the module of mystuff.py is loaded to callmystuff.py, it will execute the entire mystuff.py file line by line as it runs itself until it is completed. Then call the apple function and print C, call and print the value of tangerine as B again. For correctly running modules, save the files first and reopen them for test. You can think about a module as a specialized dictionary or container that can store Python code and be accessed with the . (dot) operator. The following one is another shorter example that runs the similar program, but, coding parts are in short cuts by expert programmers. The file name of these two lines of coding is “mystuff1.py”. mystuff = {'apple' : 'I am apples.'} print mystuff ['apple'] Page 1 (5/8/2016) Arch534 – Spring 2015 In this file, mystuff is a variable, it has a key “apple” with contents of “I am apples” declared. Then I saved this file as “mystuff1.py”. Then I could print, from other Python scripts (i.e., callmystuff1.py), the item of “apple” inside the variable of mystuff. import mystuff1 print(mystuff1.mystuff['apple']) #Note: the pair of parenthesis after the print function has not been used before Python 2.7.4. Python also has another construct that serves a similar purpose called a class. A class is a way to take a grouping of functions and data and place them inside a container so we could access them with the . (dot) operator. Classes are like modules: Python is called an “object-oriented programming language.” It is because that each program could be seen as an object used by others, which is the notion of object-oriented programming style. In Python, there is a “class” that lets you structure your program in a particular way. Using classes, we can add consistency to our programs so that they can be used systematically. Thus, classes are a good way of encapsulating functionality that can be kept together and passed around as a complete module for use in other projects. A class could be seen as a blueprint. It isn’t something in itself, it just describes how to make something. We can create lots of objects from that blueprint – known technically as instances. From the data base point of view, a class has the ability to create a data structure for containing various contents. Therefore, a class is something that just has structure, which defines how something should be laid out or structured, but doesn’t have any object (or instance) yet. Then instances should be developed next. An instance is a specific copy of the class that contains all the information. A class is simply a description of what things should look like, what variables will be grouped together, and what functions can be called to manipulate those variables. Using this description, Python can create many instances (or objects) of the class, which can then be manipulated independently. Think of a class as a cookie cutter – it is not a cookie itself, but it’s a description of what a cookie looks like, and can be used to create many individual cookies. Similarly, it could be thought as a tax form. A particular tax form is a template that requires people to fill out. So, everybody has to fill out the same type of form, but the content that people put in to the form differs from person to person. A class is like the tax form or cookie cutter that specifies what content should be like. Your copy of the form with your specific information is like an instance of the class, which specifies what your content actually is. Thus, we can create objects, rather than simply procedures or variables. Classes are defined by the keyword “class” followed by a name, a pair of parenthesis, a colon, and definitions. A class template looks like this: # Defining a class class class_name: statement 1 … statement n Exercise two: coding of a class example class Foo: keyword def __init__ (self, val): self.val = val def printval (self): print (self.val) Definition Parameter self class name colon Class member variable Instance variable The class Foo creates a class and its functions are defined inside the class (shown by indentation). Following it, the __init__(self) creates an empty object with a specific initial state. This method is called class instantiation operation. The Foo class could generate many instances, and when it is called, it needs to know which instance it is working with. Therefore, Python Page 2 (5/8/2016) S206E057 – Spring 2016 will pass the value via the self parameter. Self is a variable for the instance (or called object) being accessed. In this example, when a value of val is provided by users, it will go through the definition window of __init__, to create an instance, and put the value to val that belongs to the instance. class Foo: def __init__ (self, val): self.val = val def printval (self): print (self.val) obj1 = Foo("great") obj2 = Foo(200)edie obj1.printval() obj2.printval() In this example, after the class is defined, we create two instances of the class (or two independent objects), obj1 and obj2. When the obj1 is called, Python automatically calls the __init__ function for us and passes the value of the string “great” through the variable declaration of val to its own instance member variable of val. The same thing happens for obj2. If we want to execute a class function for an instance, the statement must have the instance declared first and followed by the function name. Thus, if we want to apply the function of printval to print, the statement must have the format of obj1.printval(). Of course, the ClassFoo could also be called by other file of callClassFoo.py to implement the functions existing in ClassFoo. Yet, the execution sequences are to implement the class file first and run the call class file to two more prints at the end. See the image on the right. If objects are created in the class file, then they could be called and used in the call class file. If objects are created outside the class file, then use the from filename import* (import all items) method to call the class. This function will only run the needed items and functions, and it is not necessary to include the filename of the class when call the functions or variables. #import ClassFoo from ClassFoo import* obj1 = Foo("great") obj2 = Foo(200) obj1.printval() obj2.printval() Exercise 3: Example of a class on applying geometry 1. Defining a class named Shape first. #An example of a class class Shape: def __init__(self, x, y): self.x = x self.y = y self.description = "This shape has not been described yet" self.author = "Nobody has claimed to make this shape yet" def area(self): return self.x * self.y Page 3 (5/8/2016) Arch534 – Spring 2015 def perimeter(self): return 2 * self.x + 2 * self.y def describe(self, text): self.description = text return self.description def authorName(self, text): self.author = text def scaleSize(self, scale): self.x = self.x * scale self.y = self.y * scale The function of __init__ creates an instance of Shape when this function is called - that is, when we create an actual shape, as opposed to the 'blueprint' we have here, __init__ is run. You will understand how this works later. The key word of self is how we refer to things in the class from within itself. Here, self is the first parameter in any function defined inside a class. Any function or variable created on the first level of indentation (that is, lines of code that start one TAB to the right of where we put class), Shape is automatically put into self. To access these functions and variables elsewhere inside the class, their name must be proceeded with self. In other words, function has its own variable scope, class has its scope as well. Variables could be defined inside the function without having self in front. But, after they are completed (function scope), they disappear. But, variables defined with self in front are active inside the class (class scope) and accessible across functions. Those variables defined in the __init__ function part with self in front will be accessible across functions inside the same class, which are the conventional ways of Python coding. 2. Making a class from the class definition How do we use a class? Here is an example, of what we call creating an instance of a class. Assume that the code example on section 3-1 has already been run: rectangle = Shape(100, 45) What has been done? The __init__ function really comes into play at this time. We create an instance of a class by first giving its name (in this case, Shape) and then, in brackets, the values to pass to the __init__ function. The init function runs (using the parameters you gave it in brackets) and then spits out an instance of that class, which in this case is assigned to the name rectangle. Think of our class instance, rectangle, as a self-contained collection of variables and functions. In the same way that we used self to access functions and variables of the class instance from within itself, we use the name that we assigned to it now (rectangle) to access functions and variables of the class instance from outside of itself. Following on from the code we ran above, we would do this: 3. Accessing attributes from outside an instance print rectangle.area() #finding the area of your rectangle: print rectangle.perimeter() #finding the perimeter of your rectangle: #describing the rectangle rectangle.describe("A wide rectangle, more than twice\ as wide as it is tall") rectangle.scaleSize(0.5) #making the rectangle 50% smaller print rectangle.area() #re-printing the new area of the rectangle As you see, where self would be used from within the class instance, its assigned name is used when outside the class. We do this to view and change the variables inside the class, and to access the functions that are there. We aren't limited to a single instance of a class - we could have as many instances as we like. We could do the following coding: Page 4 (5/8/2016) S206E057 – Spring 2016 4. More than one instance long_rectangle = Shape(120,10) fat_rectangle = Shape(130,120) Both long_rectangle and fat_rectangle have their own functions and variables contained inside them - they are totally independent of each other. There is no limit to the number of instances we could create. 5. Execution A: Completed execution codes are the following. This is the entire file of execution A. We could also separately save the class function to a file named: “ShapeClass.py” and put the remaining object instantiation plus the four print function-calls to another file named: “CallShape.py”. class Shape: def __init__(self, x, y): self.x = x self.y = y self.description = "This shape has not been described yet" self.author = "Nobody has claimed to make this shape yet" def area(self): return self.x * self.y def perimeter(self): return 2 * self.x + 2 * self.y def describe(self, text): self.description = text def authorName(self, text): self.author = text def scaleSize(self, scale): self.x = self.x * scale self.y = self.y * scale rectangle = Shape(100,45) #initiate an object of rectangle long_rectangle = Shape(120,10) #initiate an object of long_rectangle fat_rectangle = Shape(130, 120) #initiate an object of fat_rectangle print(rectangle.area()) #utilze the area function in the class. print(rectangle.perimeter()) print(long_rectangle.area()) print(fat_rectangle.area()) Instantiate objects in this area with a number of properties. Definitions inside the class. Initiate objects. Rectangle is the name of the object, Shape is the class name, 100,45 are the values to be passed into the class of Shape. Use print to print the result of the object of rectangle by the function of area. Page 5 (5/8/2016) Arch534 – Spring 2015 6. Execution B: This is the portion of the codes saved on “CallShape.py” file, which will call the class definition defined on the file of “ShapeClass.py” class by the statement of from ShapeClass import*. The ShapeClass is the file name of the class to be imported. This form will import the needed item (Shape), or all of them (represented by * sign) to the file. The “import all” might be troublesome if there are objects in the program with the same name as some items in the module. A better way is to import a module in the normal way (without the from operator) and then assign items to a local name. from ShapeClass import* # Shapeclass is the class filename and import all the items here. rectangle = Shape(100,45) #initiate an object of rectangle long_rectangle = Shape(120,10) #initiate an object of long_rectangle fat_rectangle = Shape(130, 120) #initiate an object of fat_rectangle print(rectangle.area()) print(rectangle.perimeter()) print(long_rectangle.area()) print(fat_rectangle.area()) #utilize the function of area defined in the class. Note: Object-oriented programming has a set of lingo that is associated with it as listed below for your information. 1. When we first describe a class, we are defining it (like with functions). 2. The word 'class' can be used when describing the code where the class is defined (like how a function is defined), and it can also refer to an instance of that class - this can get confusing, so make sure you know in which form we are talking about classes. 3. In class, the functions are frequently referred to as “method” when defined within a class. 4. The ability to group similar functions and variables together is called encapsulation. 5. A variable inside a class is known as an Attribute. 6. A function inside a class is known as a method. 7. A class is in the same category of things as variables, lists, dictionaries, etc. That is, they are objects. 8. A class is known as a 'data structure' - it holds data, and the methods to process that data. Note on coding techniques and conventions: 1. Class names are usually capitalized, EachWordLikeThis, but this is only one of the Python coding conventions, not a requirement. 2. The second aspect is the “values of variables inside a function”. When a variable locates inside a function, it is a local variable and the value it carries only exists inside this function. 3. The third convention on coding is to control the flow of executing the codes. Sometimes, the pass statement in Python would be used. It is used when a statement is required syntactically but you do not want any command or code to execute, which is like an empty set of braces (), [], or {}. It is a null operation, nothing happens when it executes. It also is useful in places where your code will eventually go, but has not been written yet. Here is one example: for letter in 'python': if letter == 'h': pass #or (),[], {} print('This is pass block') print('Current letter is:', letter) print("Bye") 4. Fundamental methods of developing good coding skills are to make the coding shorter and more efficient. Logical thinking and systematic processing are the critical thinking style that you have to develop for developing computational codes for architectural designs. Page 6 (5/8/2016)