Python Experiment No: 8 Study and Implementation of Object Oriented features.

Aim:- Implementation of Object Oriented features
Theory:-

Classes are a way of aggregating similar data and functions. A class is basically a scope inside which various code (especially function definitions) is executed, and the locals to this scope become attributes of the class, and of any objects constructed by this class. An object constructed by a class is called an instance of that class.
Defining a Class
To define a class, use the following format:
class ClassName:
...
...
The capitalization in this class definition is the convention, but is not required by the language.

Instance Construction
The class is a callable object that constructs an instance of the class when called. To construct an instance of the class, Foo, "call" the class object:
f = Foo()
This constructs an instance of class Foo and creates a reference to it in f.
Class Members
In order to access the member of an instance of a class, use the syntax <class instance>.<member>. It is also possible to access the members of the class definition with <class name>.<member>.

Methods
A method is a function within a class. The first argument (methods must always take at least one argument) is always the instance of the class on which the function is invoked. For example
 
>>> class Foo:
... def setx(self, x):
... self.x = x
... def bar(self):
... print self.x

 
If this code were executed, nothing would happen, at least until an instance of Foo were constructed,
and then bar were called on that instance.
 
Invoking Methods
Calling a method is much like calling a function, but instead of passing the instance as the first parameter like the list of formal parameters suggests, use the function as an attribute of the instance. 

>>> f.setx(5)
>>> f.bar()
This will output
5
 
It is possible to call the method on an arbitrary object, by using it as an attribute of the defining class
instead of an instance of that class, like so:

>>> Foo.setx(f,5)
>>> Foo.bar(f)

 
This will have the same output.

Inheritance:-
Like all object oriented languages, Python provides for inheritance. Inheritance is a simple concept by which a class can extend the facilities of another class, or in Python's case, multiple other classes. Use the following format for this:
class ClassName(superclass1,superclass2,superclass3,...):
...
The subclass will then have all the members of its superclasses. If a method is defined in the subclass and in the superclass, the member in the subclass will override the one in the superclass. In order to use the method defined in the superclass, it is necessary to call the method as an  attribute on the defining class, as in Foo.setx(f,5) above:
 
>>> class Foo:
... def bar(self):
... print "I'm doing Foo.bar()"
... x = 10
...
>>> class Bar(Foo):
... def bar(self):
... print "I'm doing Bar.bar()"
... Foo.bar(self)
... y = 9
...
>>> g = Bar()
>>> Bar.bar(g)
I'm doing Bar.bar()
I'm doing Foo.bar()
>>> g.y
9
>>> g.x
10

 
Once again, we can see what's going on under the hood by looking at the class dictionaries.
 
>>> vars(g)
{}
>>> vars(Bar)
{'y': 9, '__module__': '__main__', 'bar': <function bar at 0x4d6a04>,
'__doc__': None}
>>> vars(Foo)
{'x': 10, '__module__': '__main__', 'bar': <function bar at 0x4d6994>,'__doc__': None}
 

When we call g.x, it first looks in the vars(g) dictionary, as usual. Also as above, it checks vars(Bar) next, since g is an instance of Bar. However, thanks to inheritance, Python will check vars(Foo) if it doesn't find x in vars(Bar).

Special Methods:-
There are a number of methods which have reserved names which are used for special purposes like mimicking numerical or container operations, among other things. All of these names begin and end with two underscores. It is convention that methods beginning with a single underscore are 'private' to the scope they are introduced within.
 
Initialization and Deletion
__init__
One of these purposes is constructing an instance, and the special name for this is '__init__'. __init_- _() is called before an instance is returned (it is not necessary to return the instance manually). As an example,
 
class A:
def __init__(self):
print 'A.__init__()'
a = A()
__del__
 
Similarly, '__del__' is called when an instance is destroyed; e.g. when it is no longer referenced.
 
Operator Overloading
Operator overloading allows us to use the built-in Python syntax and operators to call functions which we define.

Encapsulation
Since all python members of a python class are accessible by functions/methods outside the class,there is no way to enforce encapsulation8 short of overriding __getattr__, __setattr__and __delattr__. General practice, however, is for the creator of a class or module to simply trust that users will use only the intended interface and avoid limiting access to the workings of the module for the sake of users who do need to access it. When using parts of a class or module other than the intended interface, keep in mind that the those parts may change in later versions of the module, and you may even cause errors or undefined behaviors in the module.



Q1) Write a syntax to create class in python.
Q2) Explain different Object Oriented features provided by python.
Q3) Explain built in class attributes.
Q4) Explain working of garbage collection in detail.
Q5) Explain Inheritance in detail.

Comments