I guess the time has come when I start walking through dangerous paths. I was delaying a little writing about Python because I might make some readers a bit mad. But I hope it does not happen, and all of you can get some learning out of this story.
Python was for me, back in the day, definitely a no-go. I like to use curly braces and semi-colons, and most of all, I avoided going into interpreted programming languages. Still, as I said in my first story:
Let your preferences aside.
My romance with Python, if I may call it like this, started during my Ph.D. when I had my beautiful, unmaintainable, and unreadable mixture of Java, R and C. Here, it was not just Mangos and Milk, but lots of crazy things. And since I decided to move all of this code to Python, this love and hate story started.
The single reason I had for choosing Python was the capability of having everything in a single code base. What was everything? It was file parsing and computing statistics over the data inside of it; It was also lots of math and matrices multiplication on this data; And finally, It was training machine learning model to achieve my objectives. Python helped me get my Ph.D. degree.
The Good, The Bad & The Ugly
I have told you more than once that I don’t like Python, but until now, the experience was good, right? Yes, so I started to think about using it more, and then I realized lots of things that made my python coding life a nightmare.
But before I start talking about my experience, let’s start with the Beauty of Python.
Python is an interpreted, high-level, general-purpose programming language. Created by Guido van Rossum and first released in 1991, Python’s design philosophy emphasizes code readability with its notable use of significant whitespace. Its language constructs and object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects.
This definition made my eyes shine the first time I read it, and I kept reading the Wikipedia article, and the Python philosophy gave me sparkles of joy.
Beautiful is better than ugly; Explicit is better than implicit; Simple is better than complex; Complex is better than complicated; And, readability counts.
A software engineer dream! But unfortunately, this definition and philosophy are not imposed by the language but instead expected from the developer. Many developers prefer coding fast and ugly rather than coding consistently and beautifully.
It was when I understood why I’m not too fond of Python. Not because of Python itself, but because of the little piece of hardware that sits between the monitor and the chair. And I am not talking about the keyboard nor the mouse.
I always said that having no explicit types in Python is a maintenance nightmare. It gets worst when everything in the code is an undefined dictionary called
d . Perfect strangers in the sense that it works for all cases, but nobody knows where it is coming from. Please give variables meaningful names and don’t let them look like strange monsters.
Python always had ways of telling the developer what is the type of a variable, in the early beginnings with comments and today with type hints. I guess most developers don’t know that. Use and abuse of type hints, it helps you, the IDE, and your colleagues who will take your code over.
Dictionaries are a trap if you have a well-defined data type, namely well-known fields and a well-known set of operations that could be applied to it. That is what classes are made for. You can access your class member using square brackets if you like, and it will help you slowly convert all your dictionaries into classes. Use the following functions in your class:
def __getitem__(self, key):
return getattr(self, key) def __setitem__(self, key, value):
setattr(self, key, value)
Classes also will help your IDE keep track of all attributes and functions it has, and it makes coding much more comfortable and faster, and guessing is not needed.
You Are So Beautiful
During university, I heard once a Professor saying while coding C.
I can solve any problem in C with one line of code, but please, do not restrict the number of characters in that line.
Of course, you can, but this will be ugly and hard to read. Unfortunately, this practice became like a pattern in Python: Solve everything with long, complicated list comprehension written in one line, to show that I know how to code.
In my opinion, list comprehensions are a great feature and should be used, but don’t make it so complicated. Remember, Python is about being beautiful and simple. I like this example a lot:
matrix = [[1, 2, 3], [4, 5], [6, 7, 8, 9]]flatten_matrix = # Normal for loop
for sublist in matrix:
for val in sublist:
flatten_matrix.append(val)# Nested List Comprehension
flatten_matrix = [val for sublist in matrix for val in sublist]
The nested list comprehension needs a few minutes to be understood if someone does not know what this is doing.
Am I Evil?
Most Python developers do not know that if you import a package, code will be triggered. It is not like some languages like Java that importing is just letting you compiler know what packages or libraries you would like to make available.
Running unwanted code is an annoying problem, mainly when packages don’t protect their scripts or intentionally run code during import. Please be explicit and don’t do that. Instead, create a parameterized initialization function. And protect your scripts with:
if __name__ == '__main__':
Importing a package in Python also opens a door for “evil”. Developers can easily play tricks on silly developers through it. Take a look on this little piece of code:
import builtinsold_open = builtins.opendef hacked_open(file, *args, **kwargs):
# here anything can be done with the file
# but for now, let's just print a string
print("Hacked Open is Working")
return old_open(file, *args, **kwargs)builtins.open = hacked_open# script.py
import coolpackif __name__ == '__main__':
with open("main.py") as file:
Yes, this code could do a lot to your file just by importing the package and opening a file: send through the network, encrypt it just for fun, you name it. Of course, it wouldn’t be obvious as this example, but serious developers building serious packages would not do it. At least if they do so, there should be documentation about it. Nevertheless, be sure about the third-party code you are using.
Another Brick in The Wall
Not necessarily the correct brick but a beautiful alone standing brick. That is the feeling sometimes when a Python application is being built with different packages.
Unfortunately, Python lets each developer decide upon coding styles. Some libraries have a beautiful code using OOP, making everything explicit like the Python Bible preach us. Some other libraries prefer a more structured programming style with global variables and only functions. And some libraries do a fantastic job on the algorithm side but apply none of any good software engineering practices.
But Python developers know how to build a time machine. Recently I faced a Python framework where you code HTML in Python alongside business logic like it was done in the late ’90s with ASP or PHP.
Deceiver of Fools
I think Python also brought to the developers’ world lots of fallacies.
…I am learning python to learn machine learning…
I guess someone needs to tell the world python is not machine learning, and machine learning is not python.
… I need to write everything in Python because the Data Scientists is doing their work in Python…
If the only reason to write a whole application in Python is that, then there is something wrong. Haven’t you heard about APIs?!
The one I like most is this one, and I already mentioned that in my second story:
“… Python is the fastest programming language for multiplying matrices …”
Yes, because Numpy is written in C.
I could go on with so many things I have already heard, but I think it is already time to change the tides.
After saying that all, I think Python is a potent tool in my toolset. Python is currently my first choice when there is some experimentation involved, maybe only parsing files, some math, or machine learning. Like a Microwave, I hate food warmed up in it, but there is nothing faster than that. Python makes you feel good about the simplicity of the code and the fast results it gives you.
The abundance of packages also enables any problem to be solved, if the packages can be put together of course. Also, the easy connectivity with C through Cython can remove any C complexity and give incredible power to Python code, for example, Numpy.
It is important to say also that some good practices make Python coding much more fun and easier in the long run.
Encapsulating code and data structures into classes is always a good idea and will increase the maintainability of the code. Type hints play another essential role in the maintainability. Abuse both.
Packages or just separate files are also an excellent way to write good maintainable code. Don’t write a thousand lines long file and think you are doing a good job. But remember, do not let implicit code to run.
But if you are only experimenting, use Python to get fast results and ignore the above recommendations, unless you want to turn your experiment into production-ready code.
Here I Go Again
My romance with Python has many ups and downs, but I can say I have lots of fun with it and not so happy times when I need to deal with code from Python “experts.” But as I said before, this is not a problem of the language but of this piece of hardware that sits between the monitor and the chair. This problem exists for all programming languages.
Writing good code should come before any other expectation. When the language relies entirely on the developer to do that, you will start noticing who has the experience and who does not.
Be the most beautiful and explicit developer you can, Python expects that from you!
Feel free to reach out to me at LinkedIn https://www.linkedin.com/in/hugo-wruck-schneider/
About the writer: Dr. Hugo Wruck Schneider
After quite some years of experience in the Industry and in the Academy, technology and programming languages became Hugo’s second tongue. Entrepreneurship was also part of this journey, among successful and also unsuccessful startups. Today, Hugo is entirely focused and driven by challenging software and data engineering problems. Starting with training complex machine learning models and making them production ready, going through the implementation of high available data engineering pipelines, designing and creating high performant algorithms in GPUs for Bioinformatics, and ending with exploring the applications of quantum computing in the bioinformatics field, Hugo is always up to the challenge. Do not hesitate to connect with Hugo on LinkedIn: https://www.linkedin.com/in/hugo-wruck-schneider/