Let's Talk Python - Some of the Unknown 👤
After working on and building things using python programming language for a while, I feel that there are some of the tricks or unknowns that this beast of a language contains and has to offer !
In this article I aim to highlight some of the unknowns that I work with from time to time and that I feel every python developer should know to get the most out of it.
Without any further ado, let's begin !
Unknown 1 - NaN
NaN itself is an unknown (Not-A-Number) when it comes to programming or mathematics, but what a python developer should focus on is the arithmetic operations on a
NaN object (that is basically
math.nan), they are bizarre !
Let's see this through an example below:
someNaN = float("NaN") someNaN == someNaN # False
Well, you see python itself couldn't figure out the infamous
NaN object. It considers as what it literally means - Not-A-Number, hence if something is not a numeric value (or can not be converted to a numeric), how come we can compare it (makes sense, right ?).
So, if there is a equality check where we need to filter out all
NaN from a list or dictionary, how can we do that ? For this python provides us with
math.isnan, so to check the
NaN equality, always use
Although, you may not encounter
NaN objects out of the blue as python is intelligent enough to not throw
NaN, instead it raises expections like
But, if you are doing data science and using numpy or pandas, be careful and check your code atleast twice to make sure you handle
Unknown 2 - global, nonlocal
Ever encountered a situation where you needed to access out-of-scope variable and didn't know the right way to do it ?
Well, I have plenty of my share experiencing the exact same situation, where I had to refactor a lot of code just to access some out-of-the scope variables !
Let's see how can we access global variables first:
someGlobalVar = True def someFunc(): return someGlobalVar def someFunc2(): someGlobalVar = False return someGlobalVar def someFunc3(): global someGlobalVar someGlobalVar = False return someGlobalVar print(someFunc(), someGlobalVar) # True, True print(someFunc2(), someGlobalVar) # False, True print(someFunc3(), someGlobalVar) # False, False
someFunc above deals with the global variable while returning
someGlobalVar, without changing the actual global variable outside the scope it directly returns it with no change at all. Python treats it as global and not local to function's scope.
someFunc2 changes the variable
someGlobalVar resulting in python to think that some new local variable is created within the function and hence does not change global variable.
global keyword to explicity say which varibale is going to be global within the function scope. Hence, after using global keyword, python knows that
someGlobalVar is coming from outside scope and it needs to change that.
So, which approach to used while developing software ?
Well, to be honest, it is better to not use too many global variables, but only to define some constants that are never going to be changed during execution.
Still, to use global variables within local scopes of functions or classes, always use
global keyword, even when you are not going to change the value, as explicit is better than implicit !
Same goes for
nonlocal keyword, always specify nonlocal variables when creating closures that requires the same.
def outer(): val1 = True def inner(): nonlocal val1 if val1: # do some stuff
nonlocal keyword will look for the nearest/immediate outer variable, if not found it will move to next outer scope and so on...
Unknown 3 - Mutable Objects
Ever tried to pass mutable objects like
dict as default arguments to a function in python ?
If not, then you have been lucky, if yes, then you know the disaster it brings (sometimes this disaster can be a blessing in disguise, but not often !).
Never ever pass mutable objects as default function arguments (except for logging purpose) !
def someFunc(a = ): a.append('Never Do This') return a print(someFunc()) # ['Never Do This'] print(someFunc()) # ['Never Do This', 'Never Do This'] print(someFunc()) # ['Never Do This', 'Never Do This', 'Never Do This']
During execution, interpretor creates some space for variable
a which is a mutable object
list and when
someFunc is called and appends some value to
a, no new address is created but at the same address where
a resides the value is added (since its mutable, value at same address can be changed), same thing happens during 2nd and 3rd call to
someFunc resulting in getting a completely different list from what we wanted.
A better way to deal with this could be as follows (as most of the tutorials and stackoverflow answers pointed out):
def someFunct(a = None): if not a: a = 
Doing this, creates a new address for list
a everytime it is called, as each call when ends destory its contents and recreate it again during next call. But for default args, the are created once !
Unknown 4 - Indexing List
Well, to access some part of the list/string in python, we immediately gets to indexing it ! But, how often do we index it using negative indices or using a method like
partition (which returns a tuple of length 3, for string object) ?
Let's look at in which case negative index could be useful:
a = [1, 2, 3] print(a[::-1]) # reverse the list in 1 line
A case where negative index makes no sense:
a = [1, 2, 3] print(a[-0:]) # equivalent to a[:], creates copy of list, [1, 2, 3]
Well, not much here, but for me, I have seldom used negative indices to access elements, sometimes it feels like a trick to do a job and sometime it is hectic to manage negative indexed slice. More than often, just to access the last element I use negative index or to reverse a list !
That's it from me, I hope you learnt something new or refreshed some of the unknowns (that's what I like to call them 😁) !
If you were here as one of the followers, then I appreciate you reading this and if you are new here, then follow me for more upcoming on-the-go articles to freshen up your developer's brain 🧙♂️
Share it with your friends, python programming beginners or seasonal python professionals!
Just starting your Open Source Journey? Don't forget to check Hello Open Source
Want to make a simple and awesome game from scratch? Check out PongPong
++ your GitHub Profile README? Check out Quote - README
Till next time!