I was recently assigned to a new project at work. Like any good software engineer I started writing the pseudocode for the modules. We use C++ at work to write our programs.
I quickly realized it's not easy to translate programming ideas to English statements without a syntactic structure. When I was whining about it to Vijay, he told me to try prototyping it in Python instead of writing pseudocode. Intrigued by this, I decided to write a prototype in Python to test how various modules will come together.
Surprisingly it took me a mere 2 hours to code up the prototype. I can't emphasize enough, how effortless it was in Python.
What makes Python an ideal choice for prototyping:
Dynamically typed language:
Python doesn't require you to declare the datatype of a variable. This lets you write a function that is generic enough to handle any kind of data. For eg:
return a if a >b else b
This function can take integers, floats, strings, a combination of any of those, or lists, dictionaries, tuples, whatever.
A list in Python need not be homogenous. This is a perfectly good list:
This lets you pack data in unique ways on the fly which can later be translated to a class or a struct in a statically typed language like C++.
Rich Set to Data-Structures:
Built-in support for lists, dictionaries, sets, etc reduces the time involved in hunting for a library that provides you those basic data-structures.
Expressive and Succinct:
The algorithms that operate on the data-structures are intuitive and simple to use. The final code is more readable than a pseudocode.
For example: Lets check if a list has an element
>>> lst = [1,2,3]
>>> res = 2 in lst
If we have to do it in C++.
list::iterator result = find(lst.begin(), lst.end(), 7);
bool res = (result != lst.end())
Python Interpreter and Help System:
This is a huge plus. The presence of interpreter not only aids you in testing snippets of code, but it acts as an help system. Lets say we want to look up the functions that operate on a List.
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__delslice__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__',
'__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__',
'__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__',
'__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append',
'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Help on built-in function sort:
L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
cmp(x, y) -> -1, 0, 1
Advantages of prototyping instead of pseudocode:
- The type definition of the datastructures emerge as we code.
- The edge cases start to emerge when you prototype.
- A set of required supporting routines.
- A better estimation of the time required to complete a task.