When I first started learning python and read about how they do class methods, I was a bit thrown off. To be an object-level method (rather than class-level, like Java
static methods), the first parameter needed to be
self. Technically, you could name it whatever you wanted, but the first parameter was supposed to be assumed to be an object of the same type as what you were working on, and it is convention to call it
I was confused. Up until then, I’d marveled at how python kept everything more concise than pretty much every other language that I’d worked with. Now they were putting in something that required extra typing. It took a while to understand why it was even necessary, especially since it was a little while yet before they even showed class-level methods. Then I realized that they would need something to distinguish between the two, and pretty much anything you did to accomplish that goal would require extra typing. So I let it go.
Then I found out that, because of that convention, you could call the method two different ways:
object.method(...). My first thoughts were that this was a fairly nice little feature, but didn’t think too much on it. Then, when I was working with Java, I realized that they sometimes doubled up some functionality with static methods as they did with object methods. Heck, even I did that sometimes, when I felt it would be helpful. With python, all methods automatically worked that way. Handy!
Then, I made another small breakthrough. I was reading a book that helped you get a basic understanding all the from the electronic nand gate up through making a CPU, then an assembly language, then higher level languages with a VM, and finally to using that higher level language for making Tetris. While learning how to build the compiler for the higher level language, it talked about how they essentially added the
this) in the background when it was compiled. I realized that there really wasn’t a good reason not to have
Self Helps with Functional Programming
Those previous moments of epiphany were nice, but don’t compare to my latest one. I started reading the beta of a new book called Fluent Python which tried to really hammer home how beautiful of a language python is, even if its users weren’t using it so beautifully. Along with that, I’ve been really hammering in on getting into a functional programming mindset, reading Java 8 Lambdas and Becoming Functional, and hopefully I’ll be able to get and read Functional Thinking somewhere down the road. Yeah, I’ve had a sudden surge in O’Reilly books added to my library lately.
Most of my time studying functional programming had revolved around using it in Java, since that’s the primary language I use, though that’s more by circumstance than choice at this point. Anyway, Fluent Python got my mind back onto python and I made an even more startling discovery about why having
self there is such a good idea. I mean, it’s such a good idea that I wonder if Guido is a super genius (some believe he is) or if this is just a side effect of an only-smart decision he made.
Before I tell why it’s so helpful in functional programming, let me give a mini primer on why OO and functional programming have generally had a bit of a disconnect when it comes to working together. They never really were meant to. In functional programming, functions work on whatever objects are passed in. In OO, objects work on themselves using functions and whatever is passed in.
The real disconnect comes into play when trying to pass named functions (not lambdas) into another function. The parameter expects a function that takes in a certain object type and returns a certain type. As an example, we’ll say that the expected function takes in a list and returns an integer. When calling this function, you decide you want to pass in the list’s method that returns the size of the list. But that doesn’t take in a list. It uses a list, but it doesn’t accept it as a parameter.
Java 8 gets around this in its method references by having the compiler attempt to automatically map where the list is (in this case, it’s the object that the method is being called on) and turning it into a lambda object that actually fits the expected function’s ‘signature’. There’s a ton going on in the background in order to let methods act as functions.
Python does not suffer from this. Why? Because of
self. It doesn’t need any special mapping happening in the background because its method is a function. This is probably the greatest (and amazingly simple) innovation to help bridge the gap between functional and object-oriented programming.
I think that the biggest reason that python was able to see how to integrate OO and functional programming the way that it has been is due to the fact that python was not originally an object-oriented language. If I remember my history correctly, Guido hadn’t used an OO language before he developed python, but he had put in functional programming early on (if not right away). His colleagues persuaded him to put in object orientation eventually, and he implemented it in a way that worked well with what he had already done (Then did it again, since he added a second preferred “style” of creating classes later on).
This is the opposite of how it usually happens. True, many (if not most) functional languages added a way of simulating objects at some point, but from what I’ve seen, they don’t fully implement all of the requirements of OOP. Also, a lot of other languages that have functional programming, added it as an afterthought further down the road. They couldn’t design their class definitions to suit the functional style without messing with all their users. They didn’t have that luxury, even if they had the idea.
There may be other languages that meld OO and functional programing together well, but I haven’t heard of them.
I hope I gave you a reason to appreciate the subtle artistry of the python language. It seems a little weird when coming to it from a “pure” OO language such as Java, but those little strange bits help it to be one of the most fluent and useful languages out there.