{"id":407608,"date":"2022-02-19T16:00:12","date_gmt":"2022-02-19T13:00:12","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/python-may-be-easy-but-its-a-goddamn-mess\/"},"modified":"2022-02-19T16:00:12","modified_gmt":"2022-02-19T13:00:12","slug":"python-may-be-easy-but-its-a-goddamn-mess","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/python-may-be-easy-but-its-a-goddamn-mess\/","title":{"rendered":"#Python may be easy but it\u2019s a goddamn mess"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a289694e2a77\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a289694e2a77\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/python-may-be-easy-but-its-a-goddamn-mess\/#Reading_code_gets_messy_with_implicitly_declared_variables\" >Reading code gets messy with implicitly declared variables<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/python-may-be-easy-but-its-a-goddamn-mess\/#Mutable_types_are_hiding_everywhere_%E2%80%94_even_in_functions\" >Mutable types are hiding everywhere \u2014 even in functions<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/python-may-be-easy-but-its-a-goddamn-mess\/#Class_variables_arent_safe_from_danger\" >Class variables aren\u2019t safe from danger<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/python-may-be-easy-but-its-a-goddamn-mess\/#Scopes_go_inside_out_sometimes\" >Scopes go inside out sometimes<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/python-may-be-easy-but-its-a-goddamn-mess\/#Some_light_at_the_horizon\" >Some light at the horizon<\/a><\/li><\/ul><\/nav><\/div>\n<p>&#8220;<strong>#Python may be easy but it\u2019s a goddamn mess<\/strong>&#8221;<br \/>\n<img decoding=\"async\" src=\"https:\/\/img-cdn.tnwcdn.com\/image?fit=796%2C417&amp;url=https%3A%2F%2Fcdn0.tnwcdn.com%2Fwp-content%2Fblogs.dir%2F1%2Ffiles%2F2022%2F02%2FUntitled-design-19.jpg&amp;signature=764963fc043d5a77bac11c3618787e90\" \/><\/p>\n<div>\n                            By industry leaders and academic researchers alike, Python is touted as one of <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/smartbear.com\/blog\/best-programming-language-to-learn-first\/\">the<\/a> <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/content.techgig.com\/7-best-programming-languages-to-learn-for-beginners-in-2021\/articleshow\/84143376.cms\">absolute<\/a> <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/flatironschool.com\/blog\/best-coding-language-for-beginners\/\">best<\/a> <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/coderdojo.com\/2015\/03\/20\/top-5-programming-languages-for-beginners\/\">languages<\/a> for novice programmers. And they\u2019re not wrong \u2014 but that doesn\u2019t mean that it doesn\u2019t confuse the shit out of programming newbies anyway.<\/p>\n<p>Take <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/dynamic-typing-in-python-307f7c22b24e\">dynamic typing<\/a> as an example. It seems amazing at first: Python literally figures out by itself what sort of value a variable might take, and you don\u2019t need to waste another line of code by telling it. This makes everything go faster!<\/p>\n<p>At first. Then you mess it up on one single line \u2014 yes, one! \u2014 and your whole project crashes before it\u2019s finished running.<\/p>\n<p>To be fair, <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/www.pcmag.com\/encyclopedia\/term\/dynamic-programming-language\">many other languages<\/a> use dynamic typing. But in the case of Python, this is only the beginning of the shit-list.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Reading_code_gets_messy_with_implicitly_declared_variables\"><\/span>Reading code gets messy with implicitly declared variables<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>When I started my PhD a couple of years ago, I wanted to develop an existing software, written by a colleague, further. I understood the basic idea of what it was doing, and my colleague had even written a paper about it as a documentation.<\/p>\n<p>But I still needed to read through thousands of lines of Python code to make sure I knew which part did what, and where I could put the new features I had in mind. That\u2019s where it got problematic\u2026<\/p>\n<p>The whole code was littered with variables that were declared nowhere. In order to understand what every variable was there for, I had to search for it throughout the whole file and, more often, across the whole project.<\/p>\n<p>Add the complication that a variable is often called one thing inside a function, but then something else when the function is actually called\u2026 And the fact that a variable can be intertwined with one class which is tied to another variable from another class which influences a totally different class\u2026 You get the idea.<\/p>\n<p>I\u2019m hardly alone with this experience. The <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/www.python.org\/dev\/peps\/pep-0020\/\">Zen of Python<\/a> clearly says explicit is better than implicit. But it\u2019s so easy to do implicit variables in Python that, especially in large projects, sh*t hits the fan very quickly.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Mutable_types_are_hiding_everywhere_%E2%80%94_even_in_functions\"><\/span>Mutable types are hiding everywhere \u2014 even in functions<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In Python, you can define functions with optional arguments \u2014 that is, arguments that you don\u2019t need to state explicitly afterwards \u2014 by providing a default value. Like so:<\/p>\n<pre>def add_five(a, b=0):&#13;\nreturn a + b + 5<\/pre>\n<p>That\u2019s a silly example, I know. But the idea is that you can call the function with one argument now, or two, and it works anyways:<\/p>\n<pre>add_five(3) # returns 8&#13;\nadd_five(3,4) # returns 12<\/pre>\n<p>This works because the expression b=0 is defining b as an integer, and integers are immutable. Now consider this:<\/p>\n<pre>def add_element(list=[]):&#13;\nlist.<a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>end(\"foo\")&#13;\nreturn list&#13;\nadd_element() # returns [\"foo\"], as expected<\/pre>\n<p>So far, so good. But what happens if you execute it again?<\/p>\n<pre>add_element() # returns [\"foo\", \"foo\"]! wtf!<\/pre>\n<p>Because a list, the [\u201cfoo\u201d] one, already exists, Python just appends its thing to that one. This works because lists, unlike integers, are <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/https-towardsdatascience-com-python-basics-mutable-vs-immutable-objects-829a0cb1530a\">mutable types<\/a>.<\/p>\n<p>\u201cInsanity is doing the same thing over and over again and expecting different results,\u201d so goes the common saying (it\u2019s often <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/quoteinvestigator.com\/2017\/03\/23\/same\/\">misattributed to Albert Einstein<\/a>). One could also say, Python plus optional arguments plus mutable objects is insanity.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Class_variables_arent_safe_from_danger\"><\/span>Class variables aren\u2019t safe from danger<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you thought that such problems are limited to the \u2014 admittedly not so ubiquitous \u2014 case of mutable objects as optional arguments, you\u2019re mistaken.<\/p>\n<p>If you do object-oriented programming \u2014 that is almost everyone \u2014 classes are everywhere in your Python code. And one of the most useful features of classes of all time is\u2026 (drumroll)<br \/>\u2026 inheritance.<\/p>\n<p>Which is just a fancy word for saying that if you have a parent class with some properties, you can create children which inherit the same properties. Like this:<\/p>\n<pre>class parent(object):&#13;\nx = 1&#13;\nclass firstchild(parent):&#13;\npass&#13;\nclass secondchild(parent):&#13;\npass&#13;\nprint(parent.x, firstchild.x, secondchild.x) # returns 1 1 1<\/pre>\n<p>This isn\u2019t a particularly brainy example, so don\u2019t copy it into your code projects. The point is, the child classes inherit the fact that x = 1, so we can call it and get the same result for the child classes as for the parent.<br \/>And if we change the x attribute of a child, it should change that child only. Like when you dyed your hair as a teen; that didn\u2019t change your parents\u2019 or your siblings\u2019 hair either. This works:<\/p>\n<pre>firstchild.x = 2&#13;\nprint(parent.x, firstchild.x, secondchild.x) # returns 1 2 1<\/pre>\n<p>And what happened when you were little and mommy dyed her hair? Your hair didn\u2019t change, right?<\/p>\n<pre>parent.x = 3&#13;\nprint(parent.x, firstchild.x, secondchild.x) # returns 3 2 3<\/pre>\n<p>Ew.<\/p>\n<p>This happens because of Python\u2019s <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/python-history.blogspot.com\/2010\/06\/method-resolution-order.html\">Method Resolution Order<\/a>. Basically, the child classes inherit everything the parents have, as long as it\u2019s not stated otherwise. So, in Python-world, if you don\u2019t protest in advance, mommy dyes your hair whenever she does hers.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Scopes_go_inside_out_sometimes\"><\/span>Scopes go inside out sometimes<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>This next one I\u2019ve stumbled over so many times.<\/p>\n<p>In Python, if you\u2019re defining a variable inside a function, this variable won\u2019t work outside the function. One says it\u2019s out of scope:<\/p>\n<pre>def myfunction(number):&#13;\nbasenumber = 2&#13;\nreturn basenumber*number&#13;\nbasenumber&#13;\n## Oh no! This is the error:&#13;\n# Traceback (most recent call last):&#13;\n# File \"\", line 1, in&#13;\n# NameError: name 'basenumber' is not defined<\/pre>\n<p>This should be rather intuitive (and no, I didn\u2019t stumble over that part).<\/p>\n<p>But what about the other way around? I mean, what if I define a variable outside a function, and then reference it inside a function?<\/p>\n<pre>x = 2&#13;\ndef add_5():&#13;\nx = x + 5&#13;\nprint(x)&#13;\nadd_5()&#13;\n## Oh dear...&#13;\n# Traceback (most recent call last):&#13;\n# File \"\", line 1, in&#13;\n# File \"\", line 2, in add_y&#13;\n# UnboundLocalError: local variable 'x' referenced before assignment<\/pre>\n<p>Strange, right? If Albert lives in a world which contains trees, and Albert lives inside of a house, surely Albert still knows what trees look like? (The tree is x, Albert\u2019s house is add_5() and Albert is 5\u2026)<\/p>\n<p>I\u2019ve stumbled over this so many times while trying to define functions in one class that get called from another class. It took me a while to get to the root of the problem.<\/p>\n<p>The thought behind this is that x inside the function is different from the x outside, and so you can\u2019t just change it like that. Like if Albert dreams about turning the trees orange \u2014 that doesn\u2019t make the trees orange of course.<\/p>\n<p>Luckily, there\u2019s a <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.python.org\/2\/faq\/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value\">simple solution<\/a> to this problem. Just slap a global before x!<\/p>\n<pre>x = 2&#13;\ndef add_5():&#13;\nglobal x&#13;\nx = x + 5&#13;\nprint(x)&#13;\nadd_5() # works!<\/pre>\n<p>So if you thought scopes only shield variables inside functions from the outside world, think again. The outside world gets protected from local variables in Python, in the same way that Albert can\u2019t color trees orange with the power of his thoughts.<\/p>\n<p>Modifying lists while iterating over them<\/p>\n<p>Eh, well\u2026 yes, I\u2019ve managed to run into such bullsh*ttery myself a couple of times.<\/p>\n<p>Consider this:<\/p>\n<pre>mynumbers = [x for x in range(10)]&#13;\n# this is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]&#13;\nfor x in range(len(mynumbers)):&#13;\nif mynumbers[x]%3 == 0:&#13;\nmynumbers.remove(mynumbers[x])&#13;\n## Ew!&#13;\n# Traceback (most recent call last):&#13;\n# File \"\", line 2, in&#13;\n# IndexError: list index out of range<\/pre>\n<p>This loop doesn\u2019t work because it deletes an element of the list every so often. The list\u2019s end therefore shifts forward. Then it\u2019s impossible to arrive at element number 10 because it\u2019s no longer there!<\/p>\n<p>One dirty but handy workaround is assigning a silly value to all elements that you want to delete, and then remove them in a next step.<\/p>\n<p>But there\u2019s a much better solution:<\/p>\n<pre>mynumbers = [x for x in range(10) if x%3 != 0]&#13;\n# that's what we wanted! [1, 2, 4, 5, 7, 8]<\/pre>\n<p>Just one line of code!<\/p>\n<p>Note that we\u2019ve already used Python\u2019s <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/all-about-python-list-comprehension-14dd979ec0d1\">list comprehension<\/a> in the broken example above, to invoke the list.<\/p>\n<p>It\u2019s the expression in the square brackets [], and is basically a short form for loops. List comprehensions are often <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/list-comprehensions-vs-for-loops-it-is-not-what-you-think-34071d4d8207\">a little bit faster<\/a> than regular loops, which is cool if you\u2019re handling large datasets.<\/p>\n<p>Here, we\u2019re just adding an if clause to tell the list comprehension that it shall not include the numbers that are divisible by 3.<\/p>\n<p>Unlike some of the phenomena described above, this isn\u2019t a case of Python madness. Even if beginners may stumble over this at first, this is Python genius.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Some_light_at_the_horizon\"><\/span>Some light at the horizon<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Back in the days, coding <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/why-python-is-not-the-programming-language-of-the-future-30ddc5339b66\">wasn\u2019t the only pain<\/a> when it came to Python-related woes.<\/p>\n<p>Python also used to be incredibly slow at execution, running anywhere from <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/hackernoon.com\/why-is-python-so-slow-e5074b6fe55b\">2 to 10 times slower<\/a> than most other languages.<\/p>\n<p>This has gotten <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/10-ways-to-speed-up-your-python-code-e3d57630b710\">a lot better now<\/a>. The <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/numpy.org\/\">Numpy package<\/a>, for example, is incredibly fast at handling lists, matrices, and the like.<\/p>\n<p><a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.python.org\/3\/library\/multiprocessing.html\">Multiprocessing<\/a> has gotten much easier with Python, too. This lets you use all your 2 or 16 or however many cores of your computer, instead of just one. I\u2019ve been running processes on 20 cores at a time and, boi, it\u2019s saved me weeks of compute time already.<\/p>\n<p>Also, as <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/top-programming-languages-for-ai-engineers-in-2020-33a9f16a80b0\">machine learning<\/a> has taken up steam over the past few years, Python has shown that it has places to go. Packages like Pytorch and Tensorflow make this <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/towardsdatascience.com\/deep-learning-with-python-neural-networks-complete-tutorial-6b53c0b06af0\">dead easy<\/a>, and other languages are struggling to keep up.<\/p>\n<p>However, the fact that Python has become better over the years doesn\u2019t guarantee a rosy future.<\/p>\n<p>Python still isn\u2019t idiot-proof. Use it with caution.<\/p>\n<p><em>This article was originally published on Medium. You can read it<a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/medium.com\/geekculture\/why-python-still-is-a-mess-1f7bf5bca281\"><span> here<\/span><\/a>.<\/em>\n                        <\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/thenextweb.com\/news\/python-may-be-easy-but-its-a-mess\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#Python may be easy but it\u2019s a goddamn mess&#8221; By industry leaders and academic researchers alike, Python is touted as one of the absolute best languages for novice programmers. And they\u2019re not wrong \u2014 but that doesn\u2019t mean that it doesn\u2019t confuse the shit out of programming newbies anyway. Take dynamic typing as an example&#8230;.<\/p>\n","protected":false},"author":1,"featured_media":407609,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/img-cdn.tnwcdn.com\/image\/tnw?filter_last=1&fit=1280,640&url=https:\/\/cdn0.tnwcdn.com\/wp-content\/blogs.dir\/1\/files\/2022\/02\/Untitled-design-19.jpg&signature=0fc70aa0f223424622be63092d37d21d","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-407608","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/407608","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=407608"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/407608\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/407609"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=407608"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=407608"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=407608"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}