{"id":2202,"date":"2024-10-30T15:46:11","date_gmt":"2024-10-30T19:46:11","guid":{"rendered":"https:\/\/www.wellformedness.com\/blog\/?p=2202"},"modified":"2024-10-30T15:46:11","modified_gmt":"2024-10-30T19:46:11","slug":"python-ellipses-considered-harmful","status":"publish","type":"post","link":"https:\/\/www.wellformedness.com\/blog\/python-ellipses-considered-harmful\/","title":{"rendered":"Python ellipses considered harmful"},"content":{"rendered":"<p>Python has a conventional object-oriented design, but it was slowly grafted onto the language, something which shows from time to time. Arguably, you see this in the convention that instance methods need <code>self<\/code> passed as their first argument, and class methods need <code>cls<\/code>as their first argument. Another place you see it is how Python does abstract classes. First, one can use definitions in the built-in\u00a0<a href=\"https:\/\/docs.python.org\/3\/library\/abc.html\"><code>abc<\/code><\/a> module, proposed in <a href=\"https:\/\/peps.python.org\/pep-3119\/\">PEP-3119<\/a>, to declare a class as abstract. But in practice most Pythonistas make a class abstract by declaring unimplemented instance methods. There are two conventional ways to do this, either with ellipses or by raising an exception, illustrated below.<\/p>\n<pre>class AbstractCandyFactory:\r\n    def make_candy(self, batch_size: int): ...\r\n<\/pre>\n<pre>class AbstractCandyFactory:\r\n    def make_candy(self, batch_size: int):\r\n        raise NotImplementedError\r\n<\/pre>\n<p>The latter is a bit more verbose, but there is actually a very good reason to prefer it to the former, elliptical version. With the exception version, if one forgets to implement <code>make_candy<\/code>\u2014say, in a concrete subclass like <code>SnickersFactory(AbstractCandyFactory)<\/code>\u2014an informative exception will be raised when <code>make_candy<\/code> is called on a <code>SnickersFactory<\/code> instance. However, in the elliptical form, the inherited form will be called, and of course will do nothing because the method has no body. This will likely cause errors down the road, but they will not be nearly as easy to track down because there is nothing to directly link the issue to the failure to override this method. For this reason alone, I consider ellipses used to declare abstract instance methods as harmful.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Python has a conventional object-oriented design, but it was slowly grafted onto the language, something which shows from time to time. Arguably, you see this in the convention that instance methods need self passed as their first argument, and class methods need clsas their first argument. Another place you see it is how Python does &hellip; <a href=\"https:\/\/www.wellformedness.com\/blog\/python-ellipses-considered-harmful\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Python ellipses considered harmful&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":""},"categories":[3,8],"tags":[],"class_list":["post-2202","post","type-post","status-publish","format-standard","hentry","category-dev","category-python"],"_links":{"self":[{"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/posts\/2202","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/comments?post=2202"}],"version-history":[{"count":4,"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/posts\/2202\/revisions"}],"predecessor-version":[{"id":2206,"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/posts\/2202\/revisions\/2206"}],"wp:attachment":[{"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/media?parent=2202"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/categories?post=2202"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wellformedness.com\/blog\/wp-json\/wp\/v2\/tags?post=2202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}