I decided to learn some Python today and to write about it as I go. When I write in this style, what I’m doing is teaching myself something new and writing while I’m learning it so you get some insight into how a professional developer thinks and learns new things.
I wanted to learn some new programming language, and I’ve been meaning to learn Python forever. Basically: I already own books on the subject, so that made the decision for me.
Today I will be reading from the book Fluent Python by Luciano Ramalho. I browsed through it enough to know it’s pretty good. It contains some insights into Python that I never understood before. Long term, I want to be able to write code in Python, and I also want to understand what people mean when they say “pythonic”.
If you are following along at home, I suggest you get a copy of this book for yourself and read along with me. I’m going to read the book bit by bit, and then I’ll probably discuss what I think of the sections I read and maybe write some code for practice, which I will publish somewhere for easy reference.
Right now I’m going to read Part I, Chapter 1, The Python Data Model. I’ll comment while I read.
We begin by talking about this weird thing in Python where you write something like
len(object) instead of
object.len(). Evidently this has something to do with that excessively hideous construct in Python where methods are named
__something__. One of the main reasons I haven’t already learned Python before now is those hideous underscore functions. Why on Earth would anybody intentionally write something that ugly into the language? Let’s read on and see if there was a good reason.
It appears that these methods written with underscores define how various language constructs are implemented. For example, the syntax
myObj[i] is implemented in the
__getitem__(i) method. For some object if you define the
__getitem__ method then that method will be called whenever you use the
[i] accessor syntax. This seems basically the same as the way Java’s
toString() method works. It has a special meaning in the language because this method will be called implicitly any time an object is used in the position of a String argument. Also, you can override the
toString method to implement it any way you want. Even so, there was no need to use ugly underscore characters to identify the
toString method as something special or unusual. Overriding a method is a familiar concept in many languages.
Similarly, when you use the
len function on an object in Python, it looks like you are calling a global:
len(myObj). However, the
len method is defined by the implementation of
__len__(self) on the object. I do not see any benefit in arranging things this way instead of just writing
myObj.len(). If anything, it just seems to obfuscate the object-oriented nature of the language.
The author of this book refers to the overall idea here and this kind of language architecture as the Python Data Model. For now I’m willing to assume and hope that there is more to it than just making an object oriented language look like it has strange global functions defined who-knows-where.
Arguably, there’s no reason a priori to prefer the Java way of doing things with
myObj.method(). It’s just syntax. But identifying certain methods as “special” and having them written a different way versus other functions—that is not just syntax.
This raises the question: what is so special about these “special” methods—which the author also calls “dunder” methods as shorthand for the double underscore? Well, we have at least a partial answer this early in the book. By implementing the
__getitem__ method on a class, that class becomes iterable. Thus, one can argue that these special methods are special because they allow the object to interact with built-in language features. The author presents a class representing a deck of cards as an example. The
__getitem__ special method is defined, and as a result we automatically get “slicing”: the expression
myDeck[:3] returns the first three elements. That is something I would call a language feature.
After reading this chapter, I have a much better understanding of these built-in functions like
len in Python. I still do not understand why the creators decided to use that horribly ugly
__uglyMethod__ notation for these. It seems like that was totally unnecessary. And it seems like nothing at all is gained by writing these special methods as if they are global unary functions like
len(myObj) instead of
myObj.len(). Whatever benefits are had by defining these special methods in the framework of the language could be had either way. The notation is just weird for weirdness’s sake.
More Python coming later—probably tomorrow.
Featured image photo by Diego Madrigal from Pexels.