By Lenin Mishra

Tick Tock, Tick Tock!

The clock is ticking. We are nearing the end of Python 2. At the time of writing this blog, approximately 6 months 20 days and 2 hours are left for Python 2.7 to retire. Don’t believe me? Check out the Python Clock. Python2.7 is not going to be supported anymore after January 1, 2020.

The buzz has already been there for a while now. If you are an active python programmer (no matter which level), you probably already know that Python 2 is soon going to become obsolete. Probably a lot of your friends, colleagues and people in the Python community have already suggested you to move on to Python 3. If you haven’t done it yet, too bad. You should really be listening more keenly to your well wishers.

Moreover, you have been missing out on a lot of stuff that Python 3 brings to the table. Python 3 has a lot of key attributes that sets it aside from Python 2. In this blog, I am going to demonstrate the 10 most important differences (In my humble opinion) between Python 2 and 3 and the advantages associated with them.

Print is a function, not a statement Print function has replaced print statement with some keyword arguments as additional features. Syntax wise, print() in Python 3 requires a parenthesis. print "My lucky number is" , 7 # Python 2 print ( "My lucky number is" , 7 ) # Python 3 In order to suppress a newline while printing, you had to use a trailing comma in Python 2. # Python 2 print 2, print 4 The above snippet produces the following results. 2 4 In order to reproduce the same results in Python 3, you have to use the end keyword argument. print ( 2 , end = " " ) print ( 4 ) My ultimate favorite addition is the file keyword argument to Python 3. The syntax for printing lines to files directly in Python 3 is much more readable than it was in Python 2. print >> open ( 'test.txt' , 'w' ), "Printing to file" # Python 2 print ( "Printing to file" , file = open ( 'test.txt' , 'w' )) # Python 3

More relatable to Mathematics 1 divided by 2 is not 0. But that is what happened in Python 2. In order to get the right value, you had to do one of the following. float ( 1 ) / 2 1.0 / 2 1 / 2.0 In Python 3, 1 divided by 2 is 0.5 (which is what it should be). If you need the truncating behavior, use // instead of / .

Meaningful comparisons Unlike Python 2, there is no more comparison of anything to everything. Try running the following in a Python 2 interpreter. print "one" > 2 print None < 2 print None < len Does it make sense? Amazingly, all of them return True. In Python 3, you cannot perform such operations anymore. When the operands don’t have a meaningful natural ordering, the interpreter returns a TypeError. print ( "one" > 2 ) The above snippet returns the following error. Traceback ( most recent call last ) : File <input_name>, line 1 , in <module> print ( "one" > 2 ) TypeError: '>' not supported between instances of 'str' and 'int' This is a great enhancement as it will drastically improve the robustness of your code.

No more xrange() In Python 2, xrange usually had the advantage of being faster than range when you are iterating over an iterable once. For example in a for loop. However in Python 3, range has been implemented as xrange . Hence, the xrange doesn’t exist anymore in Python 3. Returns a NameError if you use it. So no need to switch between range and xrange . Just use range.

Extended Iterable Unpacking With Python 3, we can perform advanced levels of iterable unpacking. For e.g. x, * y, z = range ( 5 ) print (x) print (y) print (z) When we run the above code in a Python 3 interpreter, we would get results like this. 0 [ 1 , 2 , 3 ] 4 This operation is not possible in Python 2. If you try to execute this with Python 2, you would receive a SyntaxError File <input_name>, line 1 x, *y, z = range ( 5 ) ^ SyntaxError: invalid syntax

Unicode support In Python 2, we had 2 text types - str and unicode . The str type was mostly limited to the ASCII characters. It also had one byte type called bytearray . In Python 3, we only have one text type, which is equivalent to unicode type in Python 2. We also have 2 byte types - bytes and bytearray . In Python 2, you had to prefix a string with u in order to make it unicode. For example, print type('Pylenin') print type(u'Pylenin') will produce the following results. < type 'str' > < type 'unicode' > However in Python 3, since str is the only text type, it handles unicode by default. In Python 2, you can easily concatenate a str type and byte type. However, its not possible in Python 3. x = "Python 2" + b " will remain forever" # Python 2 print x print type (x) # Python 3 print (x) print ( type (x)) The snippet for Python 2 will work and the overall type will be casted to str . However for Python 3, it will return a TypeError. # Python 2 Python 2 will remain forever < type 'str' > # Python 3 Traceback ( most recent call last ) : File <input_name>, line 1 , in <module> x = "Python 2" +b " will remain forever" TypeError: must be str, not bytes

Fixed syntax for inequality operator In Python 2, both != and <> used to work perfectly fine as inequality operators. print 2!=3 print 2<>3 However in python 3, the alternative of <> has been completely removed. Basically now there is only one way of doing it. By using the != operator.

raw_input() is gone! Just input() In Python 2, we had both input() and raw_input() . The difference was that, input() was able to read and store any data type and store it as the same type. In order to store every input as a string, you had to use raw_input() . Let’s look at some examples. # Python 2 >>> my_input = input('Enter something: ') Enter something: 123 >>> type(my_input) <type 'int'> >>> my_input = input('Enter something: ') Enter something: "Pylenin" >>> type(my_input) <type 'str'> >>> my_input = input('Enter something: ') Enter something: Pylenin # Without quotation Traceback (most recent call last): Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1, in <module> NameError: name 'Pylenin' is not defined Watch how it throws an error when we pass Pylenin without any quotations. This is really dangerous as you could expect malicious behavior in a lot of situations. In Python 3, the raw_input() has been removed. There is only the input() method and it parses the user input as string for every data type. # Python 3 >>> my_input = input ( 'Enter something: ' ) Enter something: 123 >>> type (my_input) < class ' str '> >>> my_input = input(' Enter something: ') Enter something: "Pylenin" >>> type(my_input) <class ' str '> >>> my_input = input(' Enter something: ') Enter something: Pylenin # Without quotation >>> type(my_input) <class ' str '>

Iterables instead of list In Python 2, built-in functions like range, zip, map and filter used to return a list. However in Python 3, they return iterables. If it is important for you to convert it into list, use the list() method. Now does it make sense? In some way, Yes! Usually we iterate only once over them. Hence, it is helpful in saving memory. Also dictionary methods like keys() , values() and items() do not return lists anymore. They return views. x = { "a" : 1 , "b" : 2 } print ( type (x . keys())) print ( type (x . values())) print ( type (x . items())) The above snippet will return the following result. <class 'dict_keys' > <class 'dict_values' > <class 'dict_items' >