100 Languages Speedrun: Episode 01: Python

Time to start a 100 programming languages speedrun. Every day or so, I'll be posting about a different programming language. Not just doing 100 fizzbuzzes, but trying out something that's interesting about each language.

But that's not all, some of the programming languages I will create for purpose of this series. So if you follow along, you'll see not just a lot of different programming languages, but you might also learn a thing or two about how to create your own.

I won't be shy about my opinions, and I might be even exaggerating a bit. Feel free to share your thoughts in the comments.

Episodes will all be indepedent. Target audience is people who know programming, but don't know a 100 difference languages, so I'll often use some less idiomatic ways of doing things if I think it's clearer for such reader, or if it lets me showcase specific language feature better. For languages where it's not enforced, I'll mostly stick to best-practice cross-language code formatting (2 spaces indendation, double quoted strings, no semicolons etc.), even if that language generally uses something else.

Python

And what better language to start with than Python, the most centrist and unobjectionable of them all, the Joe Manchin of programming languages. It's not really great for anything in particular, but it's good enough for a lot of thing. Among people who know multiple programming languages, it's rare to find people who love Python, but also it's rare to find any strong negative feelings about it - like a consistent 4/5 star rating. Except maybe for data scientists who only know Python, R, Matlab, and such - and they often really love Python.

It sort of does object oriented programming, but it requires a lot of awkward and unnecessary boilerplate in every method. It sort of does basic functional programming, but it would prefer if you'd stick to the few common patterns and not try anything exotic. It sort of does Unix scripting, and regexp programming, but lacks convenience functions of languages more committed to it like Ruby or Perl. It sort of does heavy numerical processing, but you'll need to jump through a lot of hoops and mostly code in a sublanguage. And so on.

I can't think of a single thing Python does best, but it is just so good at being good enough.

The closest language to Python is Ruby, and they have very different philosophy. Ruby has blocks and objects, and you can do basically everything with just that (plus a ton of syntactic sugar). Python refuses to add blocks, but instead every version adds another piece of functionality which from Ruby point of view looks like "well, you wouldn't need to do this if you just had blocks". From my interactions with programming beginners (and data scientists), such blocks-substitutes tend to be the most difficult parts of Python for them, so I don't think Python is even winning on simplicity front these days, even if Python 1 was a lot more learnable language than Ruby 1. Fortunately beginners (and data scientists) have an option to ignore all those block-substitutes, and most do just that, in spite of more experienced programmers often complaining about it.

Let's get to some coding. First, the fizzbuzz:

#!/usr/bin/env python3

def fizzbuzz(i):
  if i % 15 == 0:
    return "FizzBuzz"
  elif i % 3 == 0:
    return "Fizz"
  elif i % 5 == 0:
    return "Buzz"
  else:
    return str(i)

for i in range(1,101):
  print(fizzbuzz(i))

One of nice Python features is list comprehensions. This covers many uses of blocks - .map, .flat_map, and .filter - and in some cases it's more readable than block equivalent in Ruby.

#!/usr/bin/env python3

r = range(1, 101)
fizzbuzz = {
  k: v
  for d in
  [
    [(i, i) for i in r],
    [(i, "Fizz") for i in r if i % 5 == 0],
    [(i, "Buzz") for i in r if i % 3 == 0],
    [(i, "FizzBuzz") for i in r if i % 15 == 0]
  ]
  for (k,v) in d
}

for value in fizzbuzz.values():
  print(value)

OK, maybe this one wasn't the most readable, but if you do a lot of Python, I strongly recommend some list comprehension practice, as you'll be running into list comprehensions much more complicated than this FizzBuzz.

Another interesting feature are decorators. You write a block as if it was a function, then decorator turns it into a function you actually want. Here's a simple fib function, which thanks to memoization is O(n), even though it looks O(n^2):

#!/usr/bin/env python3

from functools import cache

@cache
def fib(n):
  if n < 2:
    return n
  else:
    return fib(n-1) + fib(n-2)

for i in range(1, 100):
  print(fib(i))

Decorators are really neat! We can also see here that Python has unlimited precission integers by default - a feature that's still quite rare, even among newer languages.

We can do more interesting things with decorators as well:

#!/usr/bin/env python3

def override(value, condition):
  def decorator(func):
    def wrapper(*args, **kwargs):
      if condition(*args, **kwargs):
        return value
      else:
        return func(*args, **kwargs)
    return wrapper
  return decorator

@override("FizzBuzz", lambda i: i%15 == 0)
@override("Buzz", lambda i: i%5 == 0)
@override("Fizz", lambda i: i%3 == 0)
def fizzbuzz(i):
  return str(i)

for i in range(1,101):
  print(fizzbuzz(i))

Decorators taking arguments have this weird tripple-nested function structure (and actually a bit more boilerplate with functools.wraps if you want your decorator to play nice with Python help system). So they're not the most readable to write, but they're great for users.

Python is a fairly "high quality" language, in that there are relatively few inconsistencies you constantly need to think about. For example all this code does exactly what you'd expect:

print(len("😉")) # 1
print([1,2] == [1,2]) # True

Python is very popular among data scientists. Jupyter notebooks allow very convenient data exploration. You can use a lot of languages in Jupyter notebooks, but Python has by far the richest ecosystem. And recently notebooks got integrated with VSCode, that's very exciting development, as it should be possible to work on a same notebook together without any extra tools! (I haven't tried that yet)

Overall, Python is a language everyone should know. It's very approachable, and you'll run into Python code sooner or later no matter what kind of coding you do.

Code

All code examples for the series will be in this repository.

Code for the Python episode is available here.