How to teach an old programmer new tricks: from C++ to Python
I learnt to code when I arrived in London in 1997, one of the thousands of young Australians completing their rite of passage from university to adulthood via an extended European trip. Faced with the reality of needing to earn a living and very little jobs on offer to those with a training in Anthropology, I turned to my other skillset, a (very) limited ability to program computers learnt during my childhood. As many others have experienced, this accidental beginning turned into a career which continues in technology to this day.
The languages I programmed were Visual Basic 5&6, C#, ASP & ASP.NET, Java, Transact SQL & PL/SQL. Other languages I had some exposure to are C++, Delphi, Smalltalk and other vendor specific 4th generation languages such as Webmethods and MuleSoft. Back then I would have described myself then as an object-orientated programmer with some formal training in CORBA. These days the term is a ‘full-stack’ developer as I have experience in databases (Oracle, SQL Server, MS SQL, MS Access), middle tier (JBOSS, Websphere, Weblogic), web tier (IIS, Tomcat etc.) and exposure to Mobile development (HTML 5, iOS). I have programmed on both Windows and Unix and used mainly Visual Studio and Eclipse as the IDE’s.
While I spent many years coding professionally, I ceased using these skills roughly 15 years ago as I transitioned into systems architecture and management. While I have occasionally had reason to write code, I am not an ex-programmer who still ‘tinkers’ in my spare time. The beginning of the masters, when we wrote python code to control the AxiDraw device, was the first code I had written in 5 years, since my training upon joining MuleSoft.
My goal for python was to be able to read and write it to a level where I could use it as my primary language in Machine Learning (ML) projects. While I may not have had a chance to get my ‘hands dirty’ with python, I have worked on projects where it was used, and am aware of its popularity. My understanding is that this is due to the inbuilt libraries for ML, the flexibility of the language, the relatively low learning curve due to its readability and cross-platform support. I hope to be able to test these features of the language and also get to a skill level where I could use the ML libraries within CPS projects during the course.
In order to achieve the above goal, there were a few milestones to demonstrate progress as we completed the Homework and Maker project. These were
Learn the basics: get comfortable with the syntax and basic functions (e.g. Arrays, loops, functions etc.); and the supporting software such as Pip, Conda, Visual Studio Code.
Use python for programming embedded compute such as the Circuit Playground Express (CPE):
Leverage Machine Learning Libraries (ML) such as TensorFlow and Pytorch for creating and training ML Models.
Be capable of setting up multiple environments for use in the Maker project
Evidence of Learnings.
During the first three homework assignments I was able to demonstrate that I had learnt the basic syntax and structure of Python. This included loops, arrays, functions etc. I (re)learnt the value of well-structured code that included guidance for others in the comments.
Tic-tac-Toe Function to make a move on the remaining board
def RestofBoard(BoardPositions, pieces): # Grab the next available positio on the rest of the board restofBoard = [1, 3, 5, 7] for leftovers in restofBoard: if CheckIFMoveAvailable(BoardPositions, leftovers) == True: MakeAMove(BoardPositions, leftovers, pieces) # Give out move back to the agent return True
There were a number of failures along the way as i learnt to tune the agent program to run against the human agent. Here is an early version of the main function which played the centre of the board first strategy.
# Lay out your pseudo code and make a move! # Check which pieces we are playing # print (board) pieces = WhichPieces(board) my_pieces = pieces print (my_pieces) BoardPositions = ConvertBoardToList(board) position = 4 # Execute Strategy # Make First Move # Try and Grab Centre isCentreAvailable = Grab_Centre(BoardPositions, my_pieces) if isCentreAvailable == False: # try and get the corner cornerAvailable = CornerPieces(BoardPositions, my_pieces) if cornerAvailable ==False: # try and grap the remainiung positions RestofBoard(BoardPositions, my_pieces)
We also covered coding for edge devices, when we ran our experiments on the Circuit Playground express (CPE).
import time from adafruit_circuitplayground.express import cpx # Set NeoPixel 0 to green as status of board, NeoPixel 1 to collecting data cpx.pixels = (0, 90, 0) # coded red, green, blue cpx.pixels = (0, 0, 90) # Pixel 1 blue when collecting data num_readings = 360 # set to any finite value you want
try: with open("/temp.csv", "a") as fp: fp.write('Time (s) (start = 11:05am), Temp (C) , 16-07-2020 \n') # headings initial = time.time() for x in range(0, num_readings): temp = cpx.temperature # do the C-to-F conversion here if you would like fp.write(str(time.time()-initial) + "," + str(temp) + "\n") # Change the value of sleep time below in seconds # 1 minute=60 sec, 5 mins=300 sec, 1 hour=3600 sec, etc. fp.flush() time.sleep(10) if cpx.button_a: break # Done, set NeoPixel 1 to green also cpx.pixels = (0, 90, 0)
My maker project used models created and trained with Google's Teachable.Machines.
The sample code was provided by Coral.AI as the code provided by Teachable Machines we could not get to run.
def main(): default_model_dir = '../all_models' default_model = 'model_edgetpu.tflite' default_labels = 'celeblabels.txt' parser = argparse.ArgumentParser() parser.add_argument('--model', help='.tflite model path', default=os.path.join(default_model_dir,default_model)) parser.add_argument('--labels', help='label file path', default=os.path.join(default_model_dir, default_labels)) args = parser.parse_args()
I had a number of failures when attempting to deploy the code from one raspberry PI to another. Something was wrong with my configuration which I could not fix. Setting up environments is the area of python I am least comfortable with.
I experienced a level of cognitive dissonance when we went through our initial lessons on python. One moment it felt so familiar and the next so alien, as while there are many similarities with languages such as Java there are also key differences. These are:
Python is very unstructured compared to languages like Java
What struck me about the syntax is just how forgiving it is. It's so ingrained within me to declare variables that it felt slightly rebellious to just instantiate them without proscribing their data type. While this has advantages in making the code easier to write, it did at times make it harder to read when we used the course code as Python gives you a lot of options for accomplishing the same task. I found myself writing a number of Print Statements and tracing outputs to find out what data type of function may return. I also found myself writing more comments in comparison to what I would normally write in Java. As Java is a strongly typed programming language it is largely self-documenting, whereas I found myself writing more comments just to track the output of functions. While it does require ‘;’ to be in the right place it is more flexible in other areas such as quotation marks.
I miss the compiler
I wish I had known that Python is not a compiled language as I spent ages looking for the compiler shortcut in Visual Studio Code (VSC). While it will parse the code before running it, it cannot guarantee that syntax errors will not occur, such as assigning the wrong data type. This contrasts with Java where if the compiler detects an operation that isn’t defined for that data type, the program will not compile and run at all. This does have benefits, for example, there are no need for overloaded methods in python as it handles these natively.
Python’s libraries are its secret weapon
When using Python for the Maker project there were a number of libraries I could use for supporting the project. Firstly, have tools like Pip and Conda which simplify environment setup. There are the ML model libraries such as TensorFlow and Teachable Machine which makes creating, training and utilising these models relatively simple. There are plenty of example code files that could be easily adjusted to suit my facial recognition use case. When I was building the website there were micro-frameworks like Flask that could be utilised.