As a Python trainer, I get to work with pynewbies across the spectrum. It doesn't matter whether they are from college or years into the industry when learning Python. The simplest language on the earth is not that intuitive. Things get even more challenging when they are well versed in a Typed-Object-Oriented-Language
During my Python Bootcamp, we get to work on a lot of Python exercises. Here are some common mistakes that my students make that seem to repeat across the board.
Checking Type
As the students get a place of type checking, they use the following snippet.
if type(value) == int:
vs
isinstance(value, int)
Part of the problem is with us, the instructors. When teaching types, we introduce type(<object>)
to find the variable type, which nudges them to use the function irrespective of the use case.
Why use one over the other?
type(value) == int
will work for all basic type checking. Making this a practice will backfire once you start writing your types, aka Classes.
Assume you have two classes,
class Parent:
pass
class Child(Parent):
pass
Let's create a child instance.
c = Child()
isinstance(c, Parent) # True
vs
type(c) == Parent # False
type(c) is Parent # False
type(c) is Child # True
type(c) == Child # True
List Creation
If you are coming from an object-oriented or strictly typed language, you have to unlearn many things when it comes to Python. Infact the simplicity will throw you off a bit.
When asked to write a program that returns area_of_square
given a list of sides, the following is the code written by a college student. Coming from C/C++, the immediate instinct is to declare a list of elements to store the result.
def calculate_area_of_square_with_list(lengths):
results = [None] * len(lengths)
for index, length in enumerate(lengths):
if type(length) == int:
results[index] = length ** 2
else:
results[index] = INVALID_INPUT
return results
Whereas Python makes our life much easier. You can create an empty list and keep appending to it as long as you want
def calculate_area_of_square_with_list(lengths):
results = []
for length in lengths:
if isinstance(length, int):
results.append(length ** 2)
else:
results.append(INVALID_INPUT)
return results
Taking it up a notch with one-liners
def calculate_area_of_square_with_list(lengths):
results = [length ** 2 if isinstance(length, int) else INVALID_INPUT for length in lengths]
Ternary Operator
Coming from Javascript, one of my students was surprised to see no Ternary operators in Python. A stackoverflow question led down to the following code.
result = {False:f"{name}\n{email}\n{designation}",
True:INVALID_INPUT}[name == '' or email == '']
Although there is nothing syntactically wrong with the above code, infact, it is a genius way to play around with dictionaries and boolean. A code like this is not-pythonic and might throw off Pythonista's a bit.
Consistent Code
Take a look at the following snippet. Do you see it? There is nothing wrong with putting the logic return 22.7*(length*length)
right into the block. It's always a good idea to keep the code consistent. Don't wrap one set of logic into a function while leaving others hanging as raw code.
What are we achieving by this? Clean and readable code
def calculate_area_of_shape(lengths):
if shape == "circle":
return 22.7*(length*length)
elif shape == "square":
return area_of_square(length)
else:
return INVALID_INPUT
List Slicing
Another relatively simple exercise that seems to throw newbies off guard.
Write a function called
middle
that takes a list returns a new list that contains all but the first and last element
Example 1
def middle(l):
l = len(l1)
l1.remove(l1[l - 1])
l1.remove(l1[0])
return l1
Example 2
def middle(l):
for index in range(len(l)):
if index == 0 or index == len(l) - 1:
l.pop(index)
return l
Python is a simple programming language, there should be a more straightforward way to do this, and there is. It is called list slicing.
def middle(l):
return l[1:-1]
Wrapped Tuples
An indexed tuple or list makes the code hard to read. Always unwrap it into proper variable names and use them.
for shape in shape_with_length:
area(shape[0], shape[1])
vs
for shape in shape_with_length:
area(shape_name=shape[0], length=shape[1])
vs
for shape in shape_with_length:
shape_name, length = shape[0], shape[1]
area(shape_name,length)
vs
for shape_name, length in shape_with_length:
area(shape_name, length)
Using Package names as file names
Whenever I introduce flask to my students, I name the file app.py
, and there will be one person in the class who calls it flask.py
that will give you an error like Flask not found in module flask.
The error occurs because the Python interpreter searches for the Flask
class in the flask.py
you created instead of the actual flask package.
Never name your module the same as the package you are trying to use.
While most of these might go unnoticed as we go up the Python ladder, teaching newbies brought out aspects usually overlooked. There are a lot more to the list as to
- Understanding Terminal vs. Python shell
- How to write REST APIs?
- Database design
- How to build projects with Python
All of these questions are answered in my #PythonToProject 4 Week Cohort