About
Swaroop C H is 26 years of age. He graduated in B.E. (Computer Science) from PESIT, Bangalore, India. He has previously worked at Yahoo! and Adobe.
Page
Support
Personal tools
Collection
Python pt-br:Programacao Orientada a Objetos
From Notes
Contents |
[edit] Introdução
Em todos os programas que escrevemos até agora, projetamos nosso programa em termos de funções, isto é, blocos de declarações que manipulam dados. Esta é a chamada maneira de programar orientada a procedimentos. Existe outra maneira de organizar seu programa que combina dados e funcionalidades e as empacota dentro de algo chamado objeto. Este é o chamado paradigma de programação orientada a objetos. Na maioria das vezes você pode usar a programação orientada a procedimentos, mas quando estamos escrevendo grandes programas ou temos um probelma que se adequa melhor a esse método, você pode usar técnicas de programação orientadas a objetos.
Classes e objetos são os dois principais aspectos da programação orientada a objetos. Uma classe cria um novo tipo onde objetos são instâncias da classe. Uma analogia é que você pode ter variáveis do tipo int o que significa dizer que variáveis que armazenam inteiros são variáveis que são instâncias (objetos) da classe int.
- Nota para Programadores de Linguagens Estáticas
- Note que mesmo os inteiros são tratados como objetos (da classe int). Isso é diferente do C++ e do Java (antes da versão 1.5) onde os inteiros são tipos primitivos nativos. Veja help(int) para mais detalhes sobre a classe.
- Programadores C# e Java 1.5 encontrarão semelhanças com os conceitos de boxing e unboxing.
Objects can store data using ordinary variables that belong to the object. Variables that belong to an object or class are called as fields. Objects can also have functionality by using functions that belong to a class. Such functions are called methods of the class. This terminology is important because it helps us to differentiate between functions and variables which are independent and those which belong to a class or object. Collectively, the fields and methods can be referred to as the attributes of that class.
Fields are of two types - they can belong to each instance/object of the class or they can belong to the class itself. They are called instance variables and class variables respectively.
A class is created using the class keyword. The fields and methods of the class are listed in an indented block.
[edit] The self
Class methods have only one specific difference from ordinary functions - they must have an extra first name that has to be added to the beginning of the parameter list, but you do not give a value for this parameter when you call the method, Python will provide it. This particular variable refers to the object itself, and by convention, it is given the name self.
Although, you can give any name for this parameter, it is strongly recommended that you use the name self - any other name is definitely frowned upon. There are many advantages to using a standard name - any reader of your program will immediately recognize it and even specialized IDEs (Integrated Development Environments) can help you if you use self.
- Note for C++/Java/C# Programmers
- The self in Python is equivalent to the this pointer in C++ and the this reference in Java and C#.
You must be wondering how Python gives the value for self and why you don't need to give a value for it. An example will make this clear. Say you have a class called MyClass and an instance of this class called MyObject. When you call a method of this object as MyObject.method(arg1, arg2), this is automatically converted by Python into MyClass.method(MyObject, arg1, arg2) - this is all the special self is about.
This also means that if you have a method which takes no arguments, then you still have to have one argument - the self.
[edit] Classes
The simplest class possible is shown in the following example.
#!/usr/bin/python # Filename: simplestclass.py class Person: pass # An empty block p = Person() print(p)
Output:
$ python simplestclass.py <__main__.Person object at 0x019F85F0>
How It Works:
We create a new class using the class statement and the name of the class. This is followed by an indented block of statements which form the body of the class. In this case, we have an empty block which is indicated using the pass statement.
Next, we create an object/instance of this class using the name of the class followed by a pair of parentheses. (We will learn more about instantiation in the next section). For our verification, we confirm the type of the variable by simply printing it. It tells us that we have an instance of the Person class in the __main__ module.
Notice that the address of the computer memory where your object is stored is also printed. The address will have a different value on your computer since Python can store the object wherever it finds space.
[edit] Object Methods
We have already discussed that classes/objects can have methods just like functions except that we have an extra self variable. We will now see an example.
#!/usr/bin/python # Filename: method.py class Person: def sayHi(self): print('Hello, how are you?') p = Person() p.sayHi() # This short example can also be written as Person().sayHi()
Output:
$ python method.py Hello, how are you?
How It Works:
Here we see the self in action. Notice that the sayHi method takes no parameters but still has the self in the function definition.
[edit] The __init__ method
There are many method names which have special significance in Python classes. We will see the significance of the __init__ method now.
The __init__ method is run as soon as an object of a class is instantiated. The method is useful to do any initialization you want to do with your object. Notice the double underscores both at the beginning and at the end of the name.
Example:
#!/usr/bin/python # Filename: class_init.py class Person: def __init__(self, name): self.name = name def sayHi(self): print('Hello, my name is', self.name) p = Person('Swaroop') p.sayHi() # This short example can also be written as Person('Swaroop').sayHi()
Output:
$ python class_init.py Hello, my name is Swaroop
How It Works:
Here, we define the __init__ method as taking a parameter name (along with the usual self). Here, we just create a new field also called name. Notice these are two different variables even though they are both called 'name'. The dotted notation allows us to differentiate between them.
Most importantly, notice that we do not explicitly call the __init__ method but pass the arguments in the parentheses following the class name when creating a new instance of the class. This is the special significance of this method.
Now, we are able to use the self.name field in our methods which is demonstrated in the sayHi method.
- Note for C++/Java/C# Programmers
- The __init__ method is analogous to a constructor in C++, C# or Java.
[edit] Class And Object Variables
We have already discussed the functionality part of classes and objects (i.e. methods), now let us learn about the data part. The data part i.e. fields are nothing but ordinary variables which are bound to the namespaces of the classes and objects. This means that these names are valid within the context of these classes and objects only. That's why they are called name spaces.
There are two types of fields - class variables and object variables which are classified depending on whether the class or the object owns the variables respectively.
Class variables are shared - they can be accessed by all instances of that class. There is only one copy of the class variable and when any one object makes a change to a class variable, that change will be seen by all the other instances.
Object variables are owned by each individual object/instance of the class. In this case, each object has its own copy of the field i.e. they are not shared and are not related in any way to the field by the same name in a different instance. An example will make this easy to understand:
#!/usr/bin/python # Filename: objvar.py class Robot: '''Represents a robot, with a name.''' # A class variable, counting the number of robots population = 0 def __init__(self, name): '''Initializes the data.''' self.name = name print('(Initializing {0})'.format(self.name)) # When this person is created, the robot # adds to the population Robot.population += 1 def __del__(self): '''I am dying.''' print('{0} is being destroyed!'.format(self.name)) Robot.population -= 1 if Robot.population == 0: print('{0} was the last one.'.format(self.name)) else: print('There are still {0:d} robots working.'.format(Robot.population)) def sayHi(self): '''Greeting by the robot. Yeah, they can do that.''' print('Greetings, my masters call me {0}.'.format(self.name)) def howMany(klass): '''Prints the current population.''' print('We have {0:d} robots.'.format(Robot.population)) howMany = classmethod(howMany) droid1 = Robot('R2-D2') droid1.sayHi() Robot.howMany() droid2 = Robot('C-3PO') droid2.sayHi() Robot.howMany() print("\nRobots can do some work here.\n") print("Robots have finished their work. So let's destroy them.") del droid1 del droid2 Robot.howMany()
Output:
(Initializing R2-D2) Greetings, my masters call me R2-D2. We have 1 robots. (Initializing C-3PO) Greetings, my masters call me C-3PO. We have 2 robots. Robots can do some work here. Robots have finished their work. So let's destroy them. R2-D2 is being destroyed! There are still 1 robots working. C-3PO is being destroyed! C-3PO was the last one. We have 0 robots.
How It Works:
This is a long example but helps demonstrate the nature of class and object variables. Here, population belongs to the Robot class and hence is a class variable. The name variable belongs to the object (it is assigned using self) and hence is an object variable.
Thus, we refer to the population class variable as Person.population and not as self.population. We refer to the object variable name using self.name notation in the methods of that object. Remember this simple difference between class and object variables. Also note that an object variable with the same name as a class variable will hide the class variable!
The howMany is actually a class method, and not an object method. Hence, it takes klass as the first argument. Note that we use the 'k' because we cannot reuse the word class which is already a statement used to create new classes.
Also, we are not yet done with the definition of 'howMany', we have to explicitly say that this is a class method, and hence wrap the function using the built-in classmethod function.
We could have also achieved the same using decorators:
@classmethod def howMany(klass): '''Prints the current population.''' print('We have {0:d} robots.'.format(Robot.population))
Decorators can be imagined to be a shortcut to calling an explicit statement, as we have seen in this example.
Observe that the __init__ method is used to initialize the Robot instance with a name. In this method, we increase the population count by 1 since we have one more robot being added. Also observe that the values of self.name is specific to each object which indicates the nature of object variables.
Remember, that you must refer to the variables and methods of the same object using the self only. This is called an attribute reference.
In this program, we also see the use of docstrings for classes as well as methods. We can access the class docstring at runtime using Person.__doc__ and the method docstring as Person.sayHi.__doc__
Just like the __init__ method, there is another special method __del__ which is called when an object is going to die i.e. it is no longer being used and is being returned to the computer system for reusing that piece of memory. In this method, we simply decrease the Person.population count by 1.
The __del__ method is run when the object is no longer in use and there is no guarantee when that method will be run. If you want to explicitly see it in action, we have to use the del statement which is what we have done here.
- Note for C++/Java/C# Programmers
- All class members (including the data members) are public and all the methods are virtual in Python.
- One exception: If you use data members with names using the double underscore prefix such as __privatevar, Python uses name-mangling to effectively make it a private variable.
- Thus, the convention followed is that any variable that is to be used only within the class or object should begin with an underscore and all other names are public and can be used by other classes/objects. Remember that this is only a convention and is not enforced by Python (except for the double underscore prefix).
- Also, note that the __del__ method is analogous to the concept of a destructor.
[edit] Inheritance
One of the major benefits of object oriented programming is reuse of code and one of the ways this is achieved is through the inheritance mechanism. Inheritance can be best imagined as implementing a type and subtype relationship between classes.
Suppose you want to write a program which has to keep track of the teachers and students in a college. They have some common characteristics such as name, age and address. They also have specific characteristics such as salary, courses and leaves for teachers and, marks and fees for students.
You can create two independent classes for each type and process them but adding a new common characteristic would mean adding to both of these independent classes. This quickly becomes unwieldy.
A better way would be to create a common class called SchoolMember and then have the teacher and student classes inherit from this class i.e. they will become sub-types of this type (class) and then we can add specific characteristics to these sub-types.
There are many advantages to this approach. If we add/change any functionality in SchoolMember, this is automatically reflected in the subtypes as well. For example, you can add a new ID card field for both teachers and students by simply adding it to the SchoolMember class. However, changes in the subtypes do not affect other subtypes. Another advantage is that if you can refer to a teacher or student object as a SchoolMember object which could be useful in some situations such as counting of the number of school members. This is called polymorphism where a sub-type can be substituted in any situation where a parent type is expected i.e. the object can be treated as an instance of the parent class.
Also observe that we reuse the code of the parent class and we do not need to repeat it in the different classes as we would have had to in case we had used independent classes.
The SchoolMember class in this situation is known as the base class or the superclass. The Teacher and Student classes are called the derived classes or subclasses.
We will now see this example as a program.
#!/usr/bin/python # Filename: inherit.py class SchoolMember: '''Represents any school member.''' def __init__(self, name, age): self.name = name self.age = age print('(Initialized SchoolMember: {0})'.format(self.name)) def tell(self): '''Tell my details.''' print('Name:"{0}" Age:"{1}"'.format(self.name, self.age), end=" ") class Teacher(SchoolMember): '''Represents a teacher.''' def __init__(self, name, age, salary): SchoolMember.__init__(self, name, age) self.salary = salary print('(Initialized Teacher: {0})'.format(self.name)) def tell(self): SchoolMember.tell(self) print('Salary: "{0:d}"'.format(self.salary)) class Student(SchoolMember): '''Represents a student.''' def __init__(self, name, age, marks): SchoolMember.__init__(self, name, age) self.marks = marks print('(Initialized Student: {0})'.format(self.name)) def tell(self): SchoolMember.tell(self) print('Marks: "{0:d}"'.format(self.marks)) t = Teacher('Mrs. Shrividya', 40, 30000) s = Student('Swaroop', 25, 75) print() # prints a blank line members = [t, s] for member in members: member.tell() # works for both Teachers and Students
Output:
$ python inherit.py (Initialized SchoolMember: Mrs. Shrividya) (Initialized Teacher: Mrs. Shrividya) (Initialized SchoolMember: Swaroop) (Initialized Student: Swaroop) Name:"Mrs. Shrividya" Age:"40" Salary: "30000" Name:"Swaroop" Age:"25" Marks: "75"
How It Works:
To use inheritance, we specify the base class names in a tuple following the class name in the class definition. Next, we observe that the __init__ method of the base class is explicitly called using the self variable so that we can initialize the base class part of the object. This is very important to remember - Python does not automatically call the constructor of the base class, you have to explicitly call it yourself.
We also observe that we can call methods of the base class by prefixing the class name to the method call and then pass in the self variable along with any arguments.
Notice that we can treat instances of Teacher or Student as just instances of the SchoolMember when we use the tell method of the SchoolMember class.
Also, observe that the tell method of the subtype is called and not the tell method of the SchoolMember class. One way to understand this is that Python always starts looking for methods in the actual type, which in this case it does. If it could not find the method, it starts looking at the methods belonging to its base classes one by one in the order they are specified in the tuple in the class definition.
A note on terminology - if more than one class is listed in the inheritance tuple, then it is called multiple inheritance.
[edit] Metaclasses
There is much more to the vast topic of object-oriented programming, but we'll touch upon a few topics lightly here so that we become aware that such concepts exist.
Just like we use classes to create objects, we can use metaclasses to create classes. Metaclasses are used to modify or introduce new behavior to classes.
Let us take an example. Let's say we want to make sure that we always create instances of only subclasses of the SchoolMember class and that we do not create instances of the SchoolMember class itself.
We can achieve this by using a concept called "abstract base classes". All that it means is that it is an abstract class which means it's a concept, and not meant to be used as a real class.
We can declare that our class is an abstract base class by using a built-in metaclass called ABCMeta.
#!/usr/bin/env python # Filename: inherit_abc.py from abc import * class SchoolMember(metaclass=ABCMeta): '''Represents any school member.''' def __init__(self, name, age): self.name = name self.age = age print('(Initialized SchoolMember: {0})'.format(self.name)) @abstractmethod def tell(self): '''Tell my details.''' print('Name:"{0}" Age:"{1}"'.format(self.name, self.age), end=" ") #pass class Teacher(SchoolMember): '''Represents a teacher.''' def __init__(self, name, age, salary): SchoolMember.__init__(self, name, age) self.salary = salary print('(Initialized Teacher: {0})'.format(self.name)) def tell(self): SchoolMember.tell(self) print('Salary: "{0:d}"'.format(self.salary)) class Student(SchoolMember): '''Represents a student.''' def __init__(self, name, age, marks): SchoolMember.__init__(self, name, age) self.marks = marks print('(Initialized Student: {0})'.format(self.name)) def tell(self): SchoolMember.tell(self) print('Marks: "{0:d}"'.format(self.marks)) t = Teacher('Mrs. Shrividya', 40, 30000) s = Student('Swaroop', 25, 75) m = SchoolMember('abc', 10) m.tell() print() # prints a blank line members = [t, s] for member in members: member.tell() # works for both Teachers and Students
Output:
(Initialized SchoolMember: Mrs. Shrividya)
(Initialized Teacher: Mrs. Shrividya)
(Initialized SchoolMember: Swaroop)
(Initialized Student: Swaroop)
Traceback (most recent call last):
File "C:\Users\swaroop\python\usingabc.py", line 44, in <module>
m = SchoolMember('abc', 10)
TypeError: Can't instantiate abstract class SchoolMember with abstract methods tell
How It Works:
We can declare the 'tell' method of the 'SchoolMember' class as an abstract method, and hence automatically we are not allowed to create an instance of the SchoolMember class.
However, we can process instances of Teacher and Student as if they are SchoolMember instances because they are subclasses.
[edit] Summary
We have now explored the various aspects of classes and objects as well as the various terminologies associated with it. We have also seen the benefits and pitfalls of object-oriented programming. Python is highly object-oriented and understanding these concepts carefully will help you a lot in the long run.
Next, we will learn how to deal with input/output and how to access files in Python.
Please add your comments by clicking on the 'Discussion' link in the left sidebar.