{"id":5007,"date":"2019-09-16T12:02:59","date_gmt":"2019-09-16T11:02:59","guid":{"rendered":"https:\/\/www.blopig.com\/blog\/?p=5007"},"modified":"2019-09-20T16:54:40","modified_gmt":"2019-09-20T15:54:40","slug":"some-more-python-tips-and-tricks","status":"publish","type":"post","link":"https:\/\/www.blopig.com\/blog\/2019\/09\/some-more-python-tips-and-tricks\/","title":{"rendered":"Some more Python tips and tricks"},"content":{"rendered":"\n<p>There are a few useful but often underutilised <a href=\"https:\/\/www.anaconda.com\/end-of-life-eol-for-python-2-7-is-coming-are-you-ready\/\">Python 3<\/a> syntactic tricks that I have picked up over the last few years; I have chosen to continue in the <a href=\"https:\/\/www.blopig.com\/blog\/2019\/04\/quick-python-tricks\/\">spirit of Mark<\/a> and share them here.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p><strong>args and kwargs<\/strong><br>This one may be old news for some, but it  managed to bypass me for a couple of years before my argument-flexibility awakening. When writing a function, sometimes it can be useful for it to be able to take an arbitrary number of arguments or keyword arguments:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def func(*args, **kwargs):\n    for idx, arg in enumerate(args):\n        print('Argument {0}: {1}'.format(idx, arg))\n    for key, value in kwargs.items():\n        print('Keyword {0} : {1}'.format(key, value))\nfunc('Hello', 'World', argtype='keyword_argument')<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"286\" height=\"62\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image.png?resize=286%2C62&#038;ssl=1\" alt=\"\" class=\"wp-image-5008\"\/><figcaption>I get a lot of use out of this function<\/figcaption><\/figure>\n\n\n\n<p>A single asterisk before the argument in the function definition denotes a variable number of inputs stored as a tuple which can be iterated inside the function; a double asterisk gives a dictionary of named variables, again accessible from within the function.<\/p>\n\n\n\n<p><strong>Unpacking iterables into function arguments<\/strong><br>Something that complements <strong>*args<\/strong> functions is the ability to unpack iterable data structures into function calls. This can be useful when, for example, your function takes a variable number of arguments which are all stored in a tuple or list:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def squared_distance(*args):\n    if len(args) % 2 == 1 or not len(args):\n        raise ValueError('squared_distance takes an even number of arguments (2 or more)')\n    dims = len(args) \/\/ 2\n    res = 0\n    for i in range(dims):\n        res += (args[i] - args[dims-1+i])**2\n    return res\n\np1 = (1, 3)\np2 = (-2, 7)\n\nprint('Ugly call:', squared_distance(p1[0], p1[1], p2[0], p2[1]))\nprint('Much nicer:', squared_distance(*p1, *p2))<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"120\" height=\"40\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image-3.png?resize=120%2C40&#038;ssl=1\" alt=\"\" class=\"wp-image-5011\"\/><figcaption>Imagine manually unpacking an iterable in 2019<\/figcaption><\/figure>\n\n\n\n<p>Perhaps this example looks contrived (because it is); we could just modify the function to take two iterables as arguments. When using libraries written by other people it often isn&#8217;t easy nor desirable to modify function definitions, and if your iterables are longer it can be tedious to unpack them manually into the function call (as in the first call in the above code). A real use of unpacking iterables in this fashion is this method I wrote to check whether my binary search tree is, in fact, a valid binary search tree:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class BinaryTree:\n# Some other methods and an __init__\n\n    def is_tree(self):\n            return self._is_tree(self.root, -np.inf, np.inf)\n    \n    def _is_tree(self, node, left_bound, right_bound):\n        if node is None:\n            return True\n        left_bounds = (left_bound, node.value)\n        right_bounds = (node.value, right_bound)\n        return node.value > left_bound and \\\n            node.value &lt; right_bound and \\\n            self._is_tree(node.left, *left_bounds) and \\\n            self._is_tree(node.right, *right_bounds)<\/pre>\n\n\n\n<p><strong>More useful print statements from your custom classes<\/strong><br>There&#8217;s something irritating about this:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class MyClass:\n    def __init__(self, data):\n        self.data = data\n    \ninst = MyClass(42)\nprint(inst)<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"353\" height=\"23\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image-4.png?resize=353%2C23&#038;ssl=1\" alt=\"\" class=\"wp-image-5012\" srcset=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image-4.png?w=353&amp;ssl=1 353w, https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image-4.png?resize=300%2C20&amp;ssl=1 300w\" sizes=\"auto, (max-width: 353px) 100vw, 353px\" \/><figcaption>Yeah, cheers for that<\/figcaption><\/figure>\n\n\n\n<p>We can change this, though. If we implement the <strong>__str__<\/strong> method of our class, the print function will look there first instead of spitting out the nonsense above:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class MyClass:\n    def __init__(self, data):\n        self.data = data\n\n    def __str__(self):\n        return 'Instance of class MyClass with data: {0}'.format(self.data)\n    \ninst = MyClass(42)\nprint(inst)<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"321\" height=\"26\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image-8.png?resize=321%2C26&#038;ssl=1\" alt=\"\" class=\"wp-image-5033\" srcset=\"https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image-8.png?w=321&amp;ssl=1 321w, https:\/\/i0.wp.com\/www.blopig.com\/blog\/wp-content\/uploads\/2019\/09\/image-8.png?resize=300%2C24&amp;ssl=1 300w\" sizes=\"auto, (max-width: 321px) 100vw, 321px\" \/><figcaption>Much better<\/figcaption><\/figure>\n\n\n\n<p>So there we have it: 3 sneaky tricks to help make your code a teeny, tiny bit better.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are a few useful but often underutilised Python 3 syntactic tricks that I have picked up over the last few years; I have chosen to continue in the spirit of Mark and share them here.<\/p>\n","protected":false},"author":61,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","wikipediapreview_detectlinks":true,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"ngg_post_thumbnail":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[19,152,260],"ppma_author":[541],"class_list":["post-5007","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-programming","tag-python","tag-tricks"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"authors":[{"term_id":541,"user_id":61,"is_guest":0,"slug":"jack","display_name":"Jack Scantlebury","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/2d30962dbe9d08db0ac110abbf9ffd5bd52f4eb7da79636d286fb584280feb2c?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/5007","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/users\/61"}],"replies":[{"embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/comments?post=5007"}],"version-history":[{"count":5,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/5007\/revisions"}],"predecessor-version":[{"id":5046,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/posts\/5007\/revisions\/5046"}],"wp:attachment":[{"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/media?parent=5007"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/categories?post=5007"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/tags?post=5007"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.blopig.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=5007"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}