{"id":5722,"date":"2017-12-31T14:14:08","date_gmt":"2017-12-31T14:14:08","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=5722"},"modified":"2017-12-31T14:47:18","modified_gmt":"2017-12-31T14:47:18","slug":"python-classes","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/python-classes\/","title":{"rendered":"Python classes"},"content":{"rendered":"<p>In my previous post I looked at some of the basics of Python. In this post I want to dig further into the syntax etc. for classes within Python.<\/p>\n<p><strong>Class naming conventions<\/strong><\/p>\n<p>We prefix a class name with the <em>class<\/em> keyword. <a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0008\/#class-names\" rel=\"noopener\" target=\"_blank\">Python naming convention<\/a> suggests the class name should be Pascal case, i.e. ClassName.<\/p>\n<p>The <a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0008\/#method-names-and-instance-variables\" rel=\"noopener\" target=\"_blank\">method naming convention<\/a>, by default, should be all lowercase with underscores (snake case) to separate words, i.e. method_name. <\/p>\n<p>Private\/protected methods and instance variables should have an underscore prefix, i.e. _private_name.<\/p>\n<p><strong>Defining a class<\/strong><\/p>\n<p>The special method name <em>__init__<\/em> can be thought of a little like a constructor, however we cannot overload it, but we can pass arguments into it<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Animal:\r\n    def __init__(self, name):\r\n        self.name = name\r\n<\/pre>\n<p><em>Note: Whilst it might appear possible to have multiple __init__ methods, it&#8217;s the last one declared which seems to be the one available to calling code.<\/em><\/p>\n<p>We terminate the line that the <em>class<\/em> keyword is on with the colon and then methods or variables start on a new line and indented with a tab.<\/p>\n<p>The <em>self<\/em> parameter passed to __init__ or any other class method is passed implicitly, i.e. we do not supply the self, Python does that for us.<\/p>\n<p><strong>Inheritance<\/strong><\/p>\n<p>Python classes support inheritance (even multiple inheritance) by declaring the base classes in a comma separated list within parenthesis, i.e.<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Animal:\r\n    def __init__(self, name):\r\n        self.name = name\r\n\r\n\r\nclass Mammal:\r\n    pass\r\n\r\n\r\nclass Dog(Animal, Mammal):\r\n    def __init__(self):\r\n        super().__init__(&quot;Dog&quot;)\r\n<\/pre>\n<p>In this example you can see how we can call the base class&#8217; <em>__init__<\/em> method. The Dog class derives from both Animal and Mammal classes (in this instance the Mammal class has no methods etc. hence uses <em>pass<\/em> statement to create the empty class).<\/p>\n<p><strong>Calling base methods in Multiple Inheritance<\/strong><\/p>\n<p>Multiple inheritance always has the issue around what base method to call in situations where there&#8217;s multiple methods of the same name, for example if we have the following<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass A:\r\n    def name(self):\r\n        print(&quot;A&quot;)\r\n\r\nclass B:\r\n    def name(self):\r\n        print(&quot;B&quot;)\r\n\r\n\r\nclass C(A, B):\r\n    pass\r\n\r\nc = C()\r\nc.name()\r\n<\/pre>\n<p>then what base class method is actually called via <em>c.name()<\/em>.<\/p>\n<p>A quick note: In the above as we&#8217;re missing the method name() on the class C, this can be seen as the following <\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass C(A, B):\r\n    def name(self):\r\n        super(C, self).name()\r\n<\/pre>\n<p>The order of resolving the methods to be called is the <a href=\"https:\/\/www.python.org\/download\/releases\/2.3\/mro\/\" rel=\"noopener\" target=\"_blank\">Method Resolution Order<\/a> (MRO). <\/p>\n<p>For our simple example, the first name() method located depends upon the order of inheritance, i.e. in the example above A&#8217;s name() is called, switching the code for C to <\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass C(B, A):\r\n    pass\r\n<\/pre>\n<p>results in B&#8217;s name method being called. <\/p>\n<p>To ensure we are explicit about which code is called, it&#8217;s best to override the name method in the subclass like this<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass C(A, B):\r\n    def name(self):\r\n        B.name(self)\r\n<\/pre>\n<p>and obviously this ensures B&#8217;s name is called.<\/p>\n<p><strong>Methods<\/strong><\/p>\n<p>We declare methods within a class using the keyword <em>def<\/em> and all methods are virtual, i.e. can be overridden in a subclass. Here&#8217;s a basic example over method overriding<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Animal:\r\n    def name(self):\r\n        pass\r\n\r\n\r\nclass Dog(Animal):\r\n    def name(self):\r\n        return &quot;Dog&quot;\r\n<\/pre>\n<p>In this example we&#8217;re using the Animal a little like an abstract class and then implementing the name method in derived classes. <\/p>\n<p><strong>Member variables\/fields<\/strong><\/p>\n<p>Let&#8217;s rewrite the previous code to now use a member variable in the base class to store the name of the Animal. <\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Animal:\r\n    _name = &quot;&quot;\r\n\r\n    def name(self):\r\n        return self._name\r\n\r\n\r\nclass Dog(Animal):\r\n    def __init__(self):\r\n        self._name = &quot;Dog&quot;\r\n<\/pre>\n<p>In this case the prefixed _ denotes a protected\/private variable. In most OO languages this encapsulates the member variable in such a way as to ensure it&#8217;s no accessible outside of the base and derived classes, however in Python it&#8217;s still available, and thus this will return the value stored within the _name variable. In PyCharm we get a hint that we&#8217;re accessing a protected member, but ultimately it&#8217;s still accessible, as per the example below<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\na = Dog()\r\nprint(a._name)\r\n<\/pre>\n<p><strong>Empty classes<\/strong><\/p>\n<p>In some cases we might want to create an empty class type, such as <\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Duck:\r\n    pass\r\n<\/pre>\n<p>If we need to then create the equivalent of a struct at runtime, then we can simply dynamically &#8220;add&#8221; variables like this<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nd = Duck()\r\nd.name = &quot;Duck&quot;\r\n<\/pre>\n<p>this leads us onto duck typing&#8230;<\/p>\n<p><strong>Duck typing<\/strong><\/p>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Duck_typing\" rel=\"noopener\" target=\"_blank\">Duck typing<\/a> allows us to declare Python type for use in other types that simple expect certain methods\/variables to exist, for example<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Car:\r\n    def __init__(self, engine):\r\n        self.engine = engine\r\n\r\n    def engine_size(self):\r\n        return self.engine.size\r\n\r\n\r\nclass EconomicalEngine:\r\n    size = 1.0\r\n\r\n\r\nclass SportEngine:\r\n    size = 3.5\r\n\r\n\r\ncar = Car(SportEngine())\r\nprint(car.engine_size())\r\n<\/pre>\n<p>In this example our Car has an engine but we do not define an Engine type, instead we simply state that the Car expects a type with a <em>size<\/em> variable. This does ofcourse means we could pass in anything with a <em>size<\/em> variable (which ofcourse might not always make much sense).<\/p>\n<p><strong>Static\/class methods<\/strong><\/p>\n<p>Up until now we&#8217;ve seen instance methods on classes. Python also includes two decorators that can be used in conjunction with our methods to make them acts in a similar way to static methods.<\/p>\n<p>The first of these is the decorator @staticmethod, for example<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Dog:\r\n    @staticmethod\r\n    def animal_type():\r\n        return &quot;Dog&quot;;\r\n\r\n# and we call the method like this\r\nprint(Dog.animal_type())\r\n# or\r\nd = Dog()\r\nprint(d.animal_type())\r\n<\/pre>\n<p>Python also includes another static-like method type which is decorated with @classmethod. A class method differs from a static method in that it includes an implicit cls variable (by convention cls is used for the first argument). For example<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Dog:\r\n    @classmethod\r\n    def name(cls):\r\n        return &quot;English Springer Spaniel&quot;\r\n\r\n# and we call the method like this\r\nprint(Dog.name())\r\n# or\r\nd = Dog()\r\nprint(d.name())\r\n<\/pre>\n<p>So what&#8217;s the difference? Both appear to allow us to work in a &#8220;static&#8221; method way but the @classmethod allows us to still get an instance of the class, but it appears that this is almost like passing an instance of a new class into the method, i.e. these appear to be equivalent. Let&#8217;s assume we have this <\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nclass Dog:\r\n    _name = &quot;Dog&quot;\r\n\r\n    @classmethod\r\n    def name(cls):\r\n        print(cls)\r\n        return cls._name\r\n\r\nd = Dog()\r\nd._name = &quot;English Springer Spaniel&quot;\r\n\r\nprint(d.name)\r\n# same as\r\nprint(Dog().name)\r\n<\/pre>\n<p>In the above we change the instance variable <em>_name<\/em> but both print statements will output &#8220;Dog&#8221; so appear functionally equivalent.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In my previous post I looked at some of the basics of Python. In this post I want to dig further into the syntax etc. for classes within Python. Class naming conventions We prefix a class name with the class keyword. Python naming convention suggests the class name should be Pascal case, i.e. ClassName. The [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[195],"tags":[],"class_list":["post-5722","post","type-post","status-publish","format-standard","hentry","category-python"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5722","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=5722"}],"version-history":[{"count":11,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5722\/revisions"}],"predecessor-version":[{"id":5734,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/5722\/revisions\/5734"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=5722"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=5722"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=5722"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}