{"id":10315,"date":"2022-02-19T13:00:12","date_gmt":"2022-02-19T13:00:12","guid":{"rendered":"http:\/\/TheNextWeb=1380846"},"modified":"2022-02-19T13: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:\/\/www.londonchiropracter.com\/?p=10315","title":{"rendered":"Python may be easy but it\u2019s a goddamn mess"},"content":{"rendered":"\n<div><img decoding=\"async\" src=\"https:\/\/img-cdn.tnwcdn.com\/image\/tnw?filter_last=1&amp;fit=1280%2C640&amp;url=https%3A%2F%2Fcdn0.tnwcdn.com%2Fwp-content%2Fblogs.dir%2F1%2Ffiles%2F2022%2F02%2FUntitled-design-19.jpg&amp;signature=0fc70aa0f223424622be63092d37d21d\" class=\"ff-og-image-inserted\"><\/div>\n<p>By industry leaders and academic researchers alike, Python is touted as one of <a href=\"https:\/\/smartbear.com\/blog\/best-programming-language-to-learn-first\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">the<\/a> <a href=\"https:\/\/content.techgig.com\/7-best-programming-languages-to-learn-for-beginners-in-2021\/articleshow\/84143376.cms\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">absolute<\/a> <a href=\"https:\/\/flatironschool.com\/blog\/best-coding-language-for-beginners\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">best<\/a> <a href=\"https:\/\/coderdojo.com\/2015\/03\/20\/top-5-programming-languages-for-beginners\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/towardsdatascience.com\/dynamic-typing-in-python-307f7c22b24e\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/www.pcmag.com\/encyclopedia\/term\/dynamic-programming-language\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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>Reading code gets messy with implicitly declared variables<\/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 href=\"https:\/\/www.python.org\/dev\/peps\/pep-0020\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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>Mutable types are hiding everywhere \u2014 even in functions<\/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): return 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 add_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=[]): list.append(\"foo\") return list add_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 href=\"https:\/\/towardsdatascience.com\/https-towardsdatascience-com-python-basics-mutable-vs-immutable-objects-829a0cb1530a\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/quoteinvestigator.com\/2017\/03\/23\/same\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">misattributed to Albert Einstein<\/a>). One could also say, Python plus optional arguments plus mutable objects is insanity.<\/p>\n<h2>Class variables aren\u2019t safe from danger<\/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): x = 1 class firstchild(parent): pass class secondchild(parent): pass print(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 print(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 print(parent.x, firstchild.x, secondchild.x) # returns 3 2 3<\/pre>\n<p>Ew.<\/p>\n<p>This happens because of Python\u2019s <a href=\"https:\/\/python-history.blogspot.com\/2010\/06\/method-resolution-order.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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>Scopes go inside out sometimes<\/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): basenumber = 2 return basenumber*number basenumber ## Oh no! This is the error: # Traceback (most recent call last): # File \"\", line 1, in # 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 def add_5(): x = x + 5 print(x) add_5() ## Oh dear... # Traceback (most recent call last): # File \"\", line 1, in # File \"\", line 2, in add_y # 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 href=\"https:\/\/docs.python.org\/2\/faq\/programming.html#why-am-i-getting-an-unboundlocalerror-when-the-variable-has-a-value\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">simple solution<\/a> to this problem. Just slap a global before x!<\/p>\n<pre>x = 2 def add_5(): global x x = x + 5 print(x) add_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)] # this is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] for x in range(len(mynumbers)): if mynumbers[x]%3 == 0: mynumbers.remove(mynumbers[x]) ## Ew! # Traceback (most recent call last): # File \"\", line 2, in # 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] # 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 href=\"https:\/\/towardsdatascience.com\/all-about-python-list-comprehension-14dd979ec0d1\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/towardsdatascience.com\/list-comprehensions-vs-for-loops-it-is-not-what-you-think-34071d4d8207\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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>Some light at the horizon<\/h2>\n<p>Back in the days, coding <a href=\"https:\/\/towardsdatascience.com\/why-python-is-not-the-programming-language-of-the-future-30ddc5339b66\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/hackernoon.com\/why-is-python-so-slow-e5074b6fe55b\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">2 to 10 times slower<\/a> than most other languages.<\/p>\n<p>This has gotten <a href=\"https:\/\/towardsdatascience.com\/10-ways-to-speed-up-your-python-code-e3d57630b710\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">a lot better now<\/a>. The <a href=\"https:\/\/numpy.org\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Numpy package<\/a>, for example, is incredibly fast at handling lists, matrices, and the like.<\/p>\n<p><a href=\"https:\/\/docs.python.org\/3\/library\/multiprocessing.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/towardsdatascience.com\/top-programming-languages-for-ai-engineers-in-2020-33a9f16a80b0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/towardsdatascience.com\/deep-learning-with-python-neural-networks-complete-tutorial-6b53c0b06af0\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">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 href=\"https:\/\/medium.com\/geekculture\/why-python-still-is-a-mess-1f7bf5bca281\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><span> here<\/span><\/a>.<\/em><\/p>\n<p> <a href=\"https:\/\/thenextweb.com\/news\/python-may-be-easy-but-its-a-mess\">Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8230;<\/p>\n","protected":false},"author":1,"featured_media":10316,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=\/wp\/v2\/posts\/10315"}],"collection":[{"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10315"}],"version-history":[{"count":0,"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=\/wp\/v2\/posts\/10315\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=\/wp\/v2\/media\/10316"}],"wp:attachment":[{"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.londonchiropracter.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}