{"id":119945,"date":"2020-10-28T13:50:50","date_gmt":"2020-10-28T13:50:50","guid":{"rendered":"https:\/\/blog.finxter.com\/?p=15834"},"modified":"2020-10-28T13:50:50","modified_gmt":"2020-10-28T13:50:50","slug":"overriding-in-python","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2020\/10\/28\/overriding-in-python\/","title":{"rendered":"Overriding in Python"},"content":{"rendered":"<p>In this article, we are going to explore the concept of overriding in Python. We are also going to explore what are magic methods and abstract classes.<\/p>\n<h2>Introduction<\/h2>\n<p>Overriding is an interesting concept in <a href=\"https:\/\/blog.finxter.com\/object-oriented-programming-terminology-cheat-sheet\/\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"[Python OOP Cheat Sheet] A Simple Overview of Object-Oriented Programming\">object-oriented programming<\/a>.\u00a0 When the method definitions of a Base Class are changed in a Subclass (Derived) Class this is called a method override.\u00a0 You are keeping the same signature of the method but changing the definition or implementation of a method defined by one of the ancestors.\u00a0 There is no special syntax or additional keywords needed to do method overriding in Python.\u00a0 It is a very important object-oriented programming concept since it makes inheritance exploit its full power.\u00a0 In essence, you are not duplicating code, thus following the programming principle of DRY (do not repeat yourself), and you can enhance the method in the subclass.<\/p>\n<p>To understand the concept of overrides, you must know the basic concepts of object-oriented programming such as classes and inheritance.\u00a0 There are many resources on the internet about OOP. \u00a0A really good resource is Finxter Academy\u2019s object-oriented Python class: <a href=\"https:\/\/academy.finxter.com\/university\/object-oriented-python\/\">https:\/\/academy.finxter.com\/university\/object-oriented-python\/<\/a><\/p>\n<h2>Need for Overrides<\/h2>\n<p>In the following example, you see how inheritance works and the problem of not overriding a method in the subclass.\u00a0 The Parent class has a method <code>whoami<\/code> that displays <code>\u201cI am a parent\u201d<\/code>.\u00a0 This method is inherited by the <code>Child<\/code> class.\u00a0 Calling the <code>whoami <\/code>method from the Child class, calls the inherited method from the Parent class and thus displays <code>\u201cI am a parent\u201d<\/code> which is wrong.<\/p>\n<p>Inheritance example with no method overriding:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Parent(): def whoami(self): print(\"I am a parent\") class Child(Parent): def play(self): print(\" I am playing\") child = Child()\nchild.whoami() # Output:\n# I am a parent\n<\/pre>\n<h2>Basic Override<\/h2>\n<p>The next example, shows how basic overriding works.\u00a0 In this example the <code>Child<\/code> class has a definition of the <code>whoami<\/code> method that overrides the method from the <code>Parent<\/code> class. Calling the <code>whoami<\/code> method from the <code>Child<\/code> class now displays <code>\u201cI am a child\u201d<\/code>.<\/p>\n<p>Basic Overriding example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#Overriding\nclass Parent(): def whoami(self): print(\"I am a parent\") class Child(Parent): def play(self): print(\" I am playing\") def whoami(self): print(\"I am a child\") parent = Parent()\nparent.whoami()\nprint()\nchild = Child()\nchild.whoami() # Output:\n# I am a parent\n# I am a child\n<\/pre>\n<h2>Extending a Method Through Overrides<\/h2>\n<p>The third example shows how you can <strong>extend<\/strong> a method in a Base Class by overriding the method in the Subclass.\u00a0 To do that we use the <code>super()<\/code> built-in function.\u00a0 It returns a proxy object that allows us to access methods of the base class.\u00a0 We can refer to the base class from the subclass without having to call the base class name explicitly.<\/p>\n<p>The <code>Employee<\/code> class has the following details for the employee: employee number, employee name, salary and, department number.\u00a0 This information is passed to the instantiated object in the <code><a href=\"https:\/\/blog.finxter.com\/python-init\/\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"What is __init__ in Python?\">__init__<\/a><\/code> method.\u00a0 The <code>showEmployee<\/code> method of the class then displays this information formatted using new lines.<\/p>\n<p>The <code>Salesman<\/code> class inherits from the <code>Employee<\/code> class.\u00a0 By default, it inherits the <code>showEmployee<\/code> method as-is from the <code>Employee<\/code> class.\u00a0 The only problem is that we want to display the commission that the salesman receives as part of the printed information.\u00a0 Here is where overriding is needed.\u00a0 We want to reuse the <code>showEmployee<\/code> method from the <code>Employee<\/code> class but we want to extend it to add the commission information.\u00a0 This is accomplished by using the <code>super()<\/code> built-in function.\u00a0 In the example below you see that in the <code>Salesman<\/code> class, <code>super()<\/code> is used twice.\u00a0 The <code>__init__<\/code> method uses it to call the <code>__init__<\/code> method of the Employee base class and the <code>showEmployee<\/code> uses it to override the <code>showEmployee<\/code> method of the <code>Employee<\/code> base class.\u00a0 In it, we display the employee information for the salesman plus the commission for the salesman.<\/p>\n<p>A third class called <code>CEO<\/code> uses the same logic as before.\u00a0 The <code>showEmployee<\/code> method in this case displays the employee information plus the stock options for the <code>CEO<\/code>.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Employee(): def __init__(self, empno, ename, salary, deptno): self.Empno = empno self.Ename = ename self.Salary = salary self.Deptno = deptno def showEmployee(self): print(\"Employee # : {}\\nEmployee Name : {}\\nSalary : {}\\nDepartment : {}\".format(self.Empno, self.Ename, self.Salary, self.Deptno)) class Salesman(Employee): def __init__(self, empno, ename, salary, deptno, comm): self.Commission = comm super().__init__(empno, ename, salary, deptno) def showEmployee(self): print(\"Salesman Profile\") super().showEmployee() print(\"Commision : \", self.Commission) class CEO(Employee): def __init__(self, empno, ename, salary, deptno, stock): self.Stock = stock super().__init__(empno, ename, salary, deptno) def showEmployee(self): print(\"CEO Profile\") super().showEmployee() print(\"Stock Options : \", self.Stock) salesman = Salesman(200, \"John Doe\", 67000, \"Sales\", 100)\nsalesman.showEmployee()\nprint(\"\")\nceo = CEO(40, \"Jennifer Smith\", 300000, \"Director\", 1000000)\nceo.showEmployee() <\/pre>\n<p>Output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Salesman Profile\nEmployee # : 200\nEmployee Name : John Doe\nSalary : 67000\nDepartment : Sales\nCommision : 100 CEO Profile\nEmployee # : 40\nEmployee Name : Jennifer Smith\nSalary : 300000\nDepartment : Director\nStock Options : 1000000\n<\/pre>\n<h2>Multiple Inheritance Overriding<\/h2>\n<p>Understanding <strong><em>multiple inheritance<\/em><\/strong> has its own challenges.\u00a0 One of them is the use of <code>super()<\/code>.\u00a0 Here is a link to an article about this issue: <a href=\"https:\/\/www.datacamp.com\/community\/tutorials\/super-multiple-inheritance-diamond-problem\">https:\/\/www.datacamp.com\/community\/tutorials\/super-multiple-inheritance-diamond-problem<\/a><\/p>\n<p>In the example below, I wanted to show a way to override a method from a subclass with multiple inheritance.\u00a0 The example consists of three classes: <code>Account<\/code>, <code>Customer<\/code>, and <code>Orders<\/code>.\u00a0 <\/p>\n<ul>\n<li>The <code>Account<\/code> class has its name and number and a display method which displays this information.\u00a0 <\/li>\n<li>The <code>Customer<\/code> class has also its name and number and a display method that displays this information.\u00a0 <\/li>\n<li>The <code>Orders<\/code> class displays the orders information for a customer in a specific account.\u00a0 It inherits from both the <code>Account<\/code> and Orders class.\u00a0 The display method in this class overrides the display methods of the base classes.\u00a0 The display method prints the Account information, the Customer information, and the Orders information<\/li>\n<\/ul>\n<p>Here&#8217;s an example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Account(): def __init__(self, name, number): self.Name = name self.Number = number def display(self): print(\"Account # : {}\\nAccount Name : {}\".format(self.Number, self.Name)) class Customer(): def __init__(self, name, number): self.Name = name self.Number = number def display(self): print(\"Customer # : {}\\nCustomer Name : {}\".format(self.Number, self.Name)) class Orders(Account, Customer): def __init__(self, acctnumber, acctname, custnumber, custname, ordnumber, ordnamename, product, qty): self.OrdNumber = ordnumber self.Product = product self.Qty = qty self.OrdName = ordnamename self.acct = Account(acctname, acctnumber) self.cust = Customer(custname, custnumber) def display(self): print(\"Order Information\") self.acct.display() self.cust.display() print(\"Order # : {}\\nOrder Name : {}\\nProduct : {}\\nQuantiy : {}\".format(self.OrdNumber, self.OrdName, self.Product, self.Qty)) acct = Account(\"AB Enterprise\", 12345)\nacct.display()\nprint(\"\")\ncust = Customer(\"John Smith\", 45678)\ncust.display()\nprint(\"\")\norder = Orders(12345, \"AB Enterprise\", 45678,\"John Smith\", 1, \"Order 1\", \"Widget\", 5, )\norder.display()\n<\/pre>\n<p>Output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Account # : 12345\nAccount Name : AB Enterprise Customer # : 45678\nCustomer Name : John Smith Order Information\nAccount # : 12345\nAccount Name : AB Enterprise\nCustomer # : 45678\nCustomer Name : John Smith\nOrder # : 1\nOrder Name : Order 1\nProduct : Widget\nQuantiy : 5\n<\/pre>\n<h2>Different Overriding Scenarios<\/h2>\n<h3>1 &#8211; Class Methods<\/h3>\n<p>Class methods are special in the sense that they can be called on a class by itself or by instances of a class.&nbsp; They bind to a class so this means that the first argument passed to the method is a class rather than an instance.<\/p>\n<p>Class methods are written similarly to regular instance methods.\u00a0 One difference is the use of the <a href=\"https:\/\/blog.finxter.com\/closures-and-decorators-in-python\/\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"Closures and Decorators in Python\">decorator <\/a><code>@classmethod<\/code> to identify that the method is a class method.\u00a0 Also, by convention, instead of using self to reference the instance of a class, <code>cls<\/code> is using to reference the class.\u00a0 For example:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Account(): @classmethod def getClassVersion(cls): print(\"Account class version is 1.0\u201d)\n<\/pre>\n<p>For more information about class methods check <a href=\"https:\/\/www.geeksforgeeks.org\/classmethod-in-python\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"https:\/\/www.geeksforgeeks.org\/classmethod-in-python\">this <\/a>website.<\/p>\n<\/p>\n<p>Here is an example of the problem you will encounter when overriding a class method:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ParentClass: @classmethod def display(cls, arg): print(\"ParentClass\") class SubClass(ParentClass): @classmethod def display(cls, arg): ret = ParentClass.create(cls, arg) print(\"Subclass\") return ret SubClass.display(\"test\")\n<\/pre>\n<p>Output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">create() takes 2 positional arguments but 3 were given<\/pre>\n<p>In the <code>Subclass<\/code>, the call to the <code>ParentClass<\/code> create method is not an unbound call the way it happens with a normal instance method.\u00a0 The outcome of this call is a <a href=\"https:\/\/blog.finxter.com\/how-to-solve-python-typeerror-int-object-is-not-iterable\/\" target=\"_blank\" rel=\"noreferrer noopener\" title=\"How to Solve Python \u201cTypeError: \u2018int\u2019 object is not iterable\u201d?\">TypeError <\/a>because the method received too many arguments.<\/p>\n<p>The solution is to use <code>super()<\/code> in order to successfully use the parent implementation.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ParentClass: @classmethod def display(cls, arg): print(\"ParentClass\") class SubClass(ParentClass): @classmethod def display(cls, arg): ret = super(SubClass, cls).create(arg) print(\"Subclass\") return ret SubClass.display(\"test\")\n<\/pre>\n<p>Output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">ParentClass\nSubclass<\/pre>\n<\/p>\n<h3>2 &#8211; Magic Methods<\/h3>\n<p><strong>What are magic methods?<\/strong><\/p>\n<p>Magic methods are a set of methods that Python automatically associates with every class definition. Your classes can override these magic methods to implement different behaviors and make them act just like Python&#8217;s built-in classes. Below you will see examples of two of the most common ones: <code>__str__<\/code> and <code>__repl__<\/code>. Using these two methods, you can implement how your objects are displayed as strings, which will be of importance while debugging and presenting the information to the user.\u00a0 Overriding these methods adds to the flexibility and power of Python. \u00a0<\/p>\n<p>The <code>__str__<\/code> method of a class is used when Python prints an object. This magic method is called by the <code>str<\/code> built-in function.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class DemoMagic(): def display(self): print(\"Demo Magic class\") varDemo = DemoMagic()\nvarDemo.display()\nstr(varDemo) <\/pre>\n<p>Output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Demo Magic class '&lt;__main__.DemoMagic object at 0x000002A7A7F64408>' class DemoMagic():\ndef display(self): print(\"Demo Magic class\") def __str__(self): return \"Override of str function\" varDemo = DemoMagic()\nvarDemo.display()\nstr(varDemo) <\/pre>\n<p>Output:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Demo Magic class 'Override of str function'\n<\/pre>\n<p>The <code>__repr__<\/code> method of a class is used to display the details of an object&#8217;s values. This magic method is called by the built-in the <code>repr<\/code> function.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class Person(object): def __init__(self, firstname, lastname): self.first = firstname self.last = lastname def __repr__(self): return \"%s %s\" % (self.first, self.last) Tom = Person(\"Tom\", \"Sawyer\")\nrepr(Tom)\n<\/pre>\n<p>Output<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">'Tom Sawyer'<\/pre>\n<p>Here is a list of magic methods.&nbsp; You can learn more about them here (<a href=\"https:\/\/www.tutorialsteacher.com\/python\/magic-methods-in-python\">https:\/\/www.tutorialsteacher.com\/python\/magic-methods-in-python<\/a>) and think how to override them to fit your needs:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">'__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__'<\/pre>\n<h3>3 &#8211; Abstract Classes\u00a0\u00a0<\/h3>\n<p>An abstract class is a blueprint that subclasses must follow. &nbsp;It can be viewed as a contract between the abstract class and the subclass.&nbsp; The abstract class tells you what to do by providing an empty abstract method and the subclass must implement it.&nbsp; By default, you must override the abstract methods defined by the abstract class.&nbsp; In other terms, we are providing a common interface for different implementations of a class.&nbsp; This is very useful for large projects where certain functionality must be implemented.<\/p>\n<p>Here is an example of an abstract class and the overrriden methods in the subclasses.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">from abc import ABC, abstractmethod class Animal(ABC): @abstractmethod def whoami(self): pass class Dog(Animal): def move(self): print(\"I am a dog\") class Cat(Animal): def move(self): print(\"I am a cat\") <\/pre>\n<h2>Conclusion<\/h2>\n<p>Overriding is a basic concept used in many places in object-oriented programming.&nbsp; You must understand it to be able to implement better classes and modify their behavior.&nbsp; This article shows you some examples where you can use overrides in Python.&nbsp; Other concepts mentioned that are worth learning more about are: magic method and abstract classes.<\/p>\n<p>The post <a href=\"https:\/\/blog.finxter.com\/overriding-in-python\/\" target=\"_blank\" rel=\"noopener noreferrer\">Overriding in Python<\/a> first appeared on <a href=\"https:\/\/blog.finxter.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Finxter<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this article, we are going to explore the concept of overriding in Python. We are also going to explore what are magic methods and abstract classes. Introduction Overriding is an interesting concept in object-oriented programming.\u00a0 When the method definitions of a Base Class are changed in a Subclass (Derived) Class this is called a [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[857],"tags":[73,468,528],"class_list":["post-119945","post","type-post","status-publish","format-standard","hentry","category-python-tut","tag-programming","tag-python","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/119945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=119945"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/119945\/revisions"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=119945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=119945"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=119945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}