For a long time, I have been focused on Java as my primary development language (and platform) for both my work and any of my small personal projects. But I have been playing with Python for more than 6 months now. The reason I picked Python, is a discussion for another day. Currently I want to focus on couple of things which I found to be weird with Python.

Before I get into that, let me make myself clear. My relationship with Python is very young and my perspective comes from a long time Java exposure and a limited exposure to other languages (read Javascript and very very little bit of Haskell). Also, within this short time with Python, I find the language as a breath of fresh air. I find it to be much more concise than what I am used to (think Java). It is really powerful. I am getting a taste of it's dynamic nature as well. These qualities of Python are well known to all and I will probably write about my impressions on specific features sometime down the line. But today I wanted to focus on couple of specific language features I found to be slightly weird in their working.

Augmented Assignment

The term might sound a bit fancy (that is what I felt when I read it), but the construct is pretty simple and probably known to all programmers (of almost any language).

a = 0
a += 1

You must have spotted the augmented assignment operator! Yep, it is += . Of course there are other similar ones like -= , *= etc. The form a += 1 is generally a shortcut of a = a + 1 . In Python also it works the same way. At least that is what I thought.

Let us try using the augmented assignment operator with list concatenation:

>>> A = [1,2,3,4]
>>> B = [5,6,7]
>>> A = A + B
>>> A
[1, 2, 3, 4, 5, 6, 7]
>>> A = [1,2,3,4]
>>> B = [5,6,7]
>>> A += B
>>> A
[1, 2, 3, 4, 5, 6, 7]
>>>

That works as expected. So I should be able to reliably use the augmented assignment operator instead of the longer form. Let us try something else now.

>>> A = [1,2,3,4]
>>> B = [5,6,7]
>>> C = A     # Why am I doing this? Wait for it.
>>> A = A + B
>>> A
[1, 2, 3, 4, 5, 6, 7]
>>> C
[1, 2, 3, 4]

This makes sense to me. The concatenation operator + creates a new object and assigns to A. And 'C' keeps pointing to the older object. This is all good and working as expected. Let us change the above using the augmented assignment operator instead.

>>> A = [1,2,3,4]
>>> B = [5,6,7]
>>> C = A
>>> A += B  # Here I have used the augmented assignment version
>>> A
[1, 2, 3, 4, 5, 6, 7]
>>> C
[1, 2, 3, 4, 5, 6, 7]

????####!!!!. What happened here? Something happened. How did it change? What did I change? The only change I made from the previous listing is that I used augmented assignment. But that changed how things work. Concatenation no longer creates a new object. It mutates the assigned object in place!!!!

That is weird to me! I figured that it is Python trying to optimize since the list is a mutable object in Python. But somehow it feels unclean, because it seems to break a promise. To a long term Python programmer, this may not be weird at all. But to me, it felt out of character to how generally Python works - predictable and explicit. It might just be my own (mis)interpretation, but it feels weird.

Boolean Operations

I am referring to the and and or operators. In Python they mean exactly what they say. The and refers to && (conjunction) in other languages like Java and or refers to || (disjunction) in other languages. In most other languages, using these operators leads to boolean results. By not in Python! These operators return one of the objects which is an outcome of the corresponding expression. One of the underlying principles behind this is Python's concept of truth values. Let me illustrate this with some examples:

>>> "" and 23
''
>>> "add" and "subtract"
'subtract'
>>> "" or 23
23
>>> "add" or "subtract"
'add'

In all these examples, you see that and and or are not returning any booleans. They work based on truth value concepts of Python and return the objects involved as per the truth value rules. Let us see its usage below:

>>> def calc_simple_interest(principal, rate, tenure):
...     p = principal if principal else 0
...     r = rate if rate else 10
...     t = tenure if tenure else 5
...     print("Returning interest for %d at %d percent for %d years" % (p,r,t))
...     return p * (r/100) * t
...
>>> calc_simple_interest(1000,5,3)
Returning interest for 1000 at 5 percent for 3 years
150.0
>>> calc_simple_interest(1000,0,0)
Returning interest for 1000 at 10 percent for 5 years
500.0
>>> calc_simple_interest(1000,8,0)
Returning interest for 1000 at 8 percent for 5 years
400.0
>>> calc_simple_interest(1000,8,None)
Returning interest for 1000 at 8 percent for 5 years
400.0

The above example is a convoluted and contrived way to handle default values (since Python has function argument defaults). But to somebody reading through that code, it still makes reasonable sense. Now let me change it.

>>> def calc_simple_interest(principal, rate, tenure):
...     p = principal or 0
...     r = rate or 10
...     t = tenure or 5
...     print("Returning interest for %d at %d percent for %d years" % (p,r,t))
...     return p * (r/100) * t
...
>>> calc_simple_interest(1000,5,3)
Returning interest for 1000 at 5 percent for 3 years
150.0
>>> calc_simple_interest(1000,0,0)
Returning interest for 1000 at 10 percent for 5 years
500.0
>>> calc_simple_interest(1000,8,0)
Returning interest for 1000 at 8 percent for 5 years
400.0
>>> calc_simple_interest(1000,8,None)
Returning interest for 1000 at 8 percent for 5 years
400.0
>>>

Now that is Python's or operator working its way to give us the exact same behavior as the 'ternary if' used before.

The way the logical operators work in Python felt weird to me. But I did not feel very unclean about it like the last one. It just was different.

In Closing

These are two cases where I felt Python to be slightly weird in its ways. There might be others and may be I will find them down the line (and I will share them if I do).

Though I have highlighted what I felt weird about Python, it does not mean that I don't like the language. On the contrary, I actually like it quite a lot. But just like anything/anybody who you like/love a lot has some small imperfections, so does Python. In fact, it is those imperfections which make them unique and differentiated to us. That is what this does to Python too.


Comments

comments powered by Disqus