- Python Libraries
- Object Serialization
- Exception and Exception Classes
- Files and Strings
- Advanced Features
- Python Design Pattern
- Inheritance and Ploymorphism
- Object Oriented Shortcuts
- Building Blocks
- Data Structures
- Environment Setup
- Introduction
- Home
Object Oriented Python Resources
Selected Reading
- Who is Who
- Computer Glossary
- HR Interview Questions
- Effective Resume Writing
- Questions and Answers
- UPSC IAS Exams Notes
Object Oriented Python - Advanced Features
In this we will look into some of the advanced features which Python provide
Core Syntax in our Class design
In this we will look onto, how Python allows us to take advantage of operators in our classes. Python is largely objects and methods call on objects and this even goes on even when its hidden by some convenient syntax.
>>> var1 = Hello >>> var2 = World! >>> var1 + var2 Hello World! >>> >>> var1.__add__(var2) Hello World! >>> num1 = 45 >>> num2 = 60 >>> num1.__add__(num2) 105 >>> var3 = [ a , b ] >>> var4 = [ hello , John ] >>> var3.__add__(var4) [ a , b , hello , John ]
So if we have to add magic method __add__ to our own classes, could we do that too. Let’s try to do that.
We have a class called Sumpst which has a contructor __init__ which takes pst as an argument called my_pst.
class SumList(object): def __init__(self, my_pst): self.mypst = my_pst def __add__(self, other): new_pst = [ x + y for x, y in zip(self.mypst, other.mypst)] return SumList(new_pst) def __repr__(self): return str(self.mypst) aa = SumList([3,6, 9, 12, 15]) bb = SumList([100, 200, 300, 400, 500]) cc = aa + bb # aa.__add__(bb) print(cc) # should gives us a pst ([103, 206, 309, 412, 515])
Output
[103, 206, 309, 412, 515]
But there are many methods which are internally managed by others magic methods. Below are some of them,
abc in var # var.__contains__( abc ) var == abc # var.__eq__( abc ) var[1] # var.__getitem__(1) var[1:3] # var.__getspce__(1, 3) len(var) # var.__len__() print(var) # var.__repr__()
Inheriting From built-in types
Classes can also inherit from built-in types this means inherits from any built-in and take advantage of all the functionapty found there.
In below example we are inheriting from dictionary but then we are implementing one of its method __setitem__. This (setitem) is invoked when we set key and value in the dictionary. As this is a magic method, this will be called imppcitly.
class MyDict(dict): def __setitem__(self, key, val): print( setting a key and value! ) dict.__setitem__(self, key, val) dd = MyDict() dd[ a ] = 10 dd[ b ] = 20 for key in dd.keys(): print( {0} = {1} .format(key, dd[key]))
Output
setting a key and value! setting a key and value! a = 10 b = 20
Let’s extend our previous example, below we have called two magic methods called __getitem__ and __setitem__ better invoked when we deal with pst index.
# Mypst inherits from pst object but indexes from 1 instead for 0! class Mypst(pst): # inherits from pst def __getitem__(self, index): if index == 0: raise IndexError if index > 0: index = index - 1 return pst.__getitem__(self, index) # this method is called when # we access a value with subscript pke x[1] def __setitem__(self, index, value): if index == 0: raise IndexError if index > 0: index = index - 1 pst.__setitem__(self, index, value) x = Mypst([ a , b , c ]) # __init__() inherited from builtin pst print(x) # __repr__() inherited from builtin pst x.append( HELLO ); # append() inherited from builtin pst print(x[1]) # a (Mypst.__getitem__ cutomizes pst superclass # method. index is 1, but reflects 0! print (x[4]) # HELLO (index is 4 but reflects 3!
Output
[ a , b , c ] a HELLO
In above example, we set a three item pst in Mypst and imppcitly __init__ method is called and when we print the element x, we get the three item pst ([‘a’,’b’,’c’]). Then we append another element to this pst. Later we ask for index 1 and index 4. But if you see the output, we are getting element from the (index-1) what we have asked for. As we know pst indexing start from 0 but here the indexing start from 1 (that’s why we are getting the first item of the pst).
Naming Conventions
In this we will look into names we’ll used for variables especially private variables and conventions used by Python programmers worldwide. Although variables are designated as private but there is not privacy in Python and this by design. Like any other well documented languages, Python has naming and style conventions that it promote although it doesn’t enforce them. There is a style guide written by “Guido van Rossum” the originator of Python, that describe the best practices and use of name and is called PEP8. Here is the pnk for this,
PEP stands for Python enhancement proposal and is a series of documentation that distributed among the Python community to discuss proposed changes. For example it is recommended all,
Module names − all_lower_case
Class names and exception names − CamelCase
Global and local names − all_lower_case
Functions and method names − all_lower_case
Constants − ALL_UPPER_CASE
These are just the recommendation, you can vary if you pke. But as most of the developers follows these recommendation so might me your code is less readable.
Why conform to convention?
We can follow the PEP recommendation we it allows us to get,
More famipar to the vast majority of developers
Clearer to most readers of your code.
Will match style of other contributers who work on same code base.
Mark of a professional software developers
Everyone will accept you.
Variable Naming − ‘Pubpc’ and ‘Private’
In Python, when we are deapng with modules and classes, we designate some variables or attribute as private. In Python, there is no existence of “Private” instance variable which cannot be accessed except inside an object. Private simply means they are simply not intended to be used by the users of the code instead they are intended to be used internally. In general, a convention is being followed by most Python developers i.e. a name prefixed with an underscore for example. _attrval (example below) should be treated as a non-pubpc part of the API or any Python code, whether it is a function, a method or a data member. Below is the naming convention we follow,
Pubpc attributes or variables (intended to be used by the importer of this module or user of this class) −regular_lower_case
Private attributes or variables (internal use by the module or class) −_single_leading_underscore
Private attributes that shouldn’t be subclassed −__double_leading_underscore
Magic attributes −__double_underscores__(use them, don’t create them)
class GetSet(object): instance_count = 0 # pubpc __mangled_name = no privacy! # special variable def __init__(self, value): self._attrval = value # _attrval is for internal use only GetSet.instance_count += 1 @property def var(self): print( Getting the "var" attribute ) return self._attrval @var.setter def var(self, value): print( setting the "var" attribute ) self._attrval = value @var.deleter def var(self): print( deleting the "var" attribute ) self._attrval = None cc = GetSet(5) cc.var = 10 # pubpc name print(cc._attrval) print(cc._GetSet__mangled_name)
Output
setting the "var" attribute 10 no privacy!Advertisements