Functions vs. Classes?

The more I get into small pieces of code I hack together the more the question grows in me when I can just use a function and when I have to make a class (with functions of course :grinning:). For most of the problems I could just define functions without ever making a class and be good. What are the rules, when to use classes (OOP) and when not?

Python is a language that emphasizes readability, so you may ask yourself, “Is my object performing an action, or is something happening to my object?” For example, a dog can eat, but generally you have to feed it in order for it to eat. A more in-depth explanation can be found on this Stack Overflow thread.

I was poking around Wikipedia to flesh out my answer, and the programming paradigm entry is actually really interesting!

Very interesting. Although i wouldn’t have described it so succinctly, the Duck.kill() example is how I think about it.

If a class is an object blueprint, any members it has should be the applicable actions (verbs) of that class, or put another way, the things that it can do, if it is an action that impacts the object as an external influence, it’s a function (or member of something else).

Great reading though as this clearly is a grey area in Python.

Thank you @koncerna that was a good read. Especially I now understand better the difference between a function and a method.

By the way: your second link seems broken, it would be interesting too, to read.

If you look at Python then you can kind of see they do both. Take a string for instance:

"hi there".split()

vs.

len("hi there")

The dumb thing about len() and similar functions is they just call a function inside the object (in this case __len__). This is actually a criticism of Python because the division is seemingly arbitrary and making len() work on multiple objects involves defining a function inside the class anyway, so why bother? Rather than having a len() function that just calls obj.__len__() just have a obj.length() function and keep things consistent.

So, it’s arbitrary, but I think when most people create classes they usually put everything on the class and only add the __BLAH__ methods when they want it to work with the Python built-in functions. For you, go with what’s simplest, and follow this progression works:

  1. Write your code with simple functions to get it working.
  2. When you see that you’re basically doing a bunch of func(data) calls that could just be data.func() then refactor it into a class.
  3. Or, if you find that you need to add new functionality to this module of functions, but the new functionality doesn’t really fit into the module, then make a class and extend it.
  4. Or, If you have a function of functions in a module and they really could be classified into separate concepts, then make classes for them.

Now, as for how to think about objects and the functions they have you generally have two types of OOP:

Message Passing: There’s the original OOP from smalltalk which was message passing based. You sent messages to objects, and the function’s name was the message endpoint with the arguments being the payload, and it returned a reply. So in this case it was like sending an email to a service with commands and then waiting for a reply. Ruby is more like this, and this is the simpler and easier to understand OOP.

Methods of Objects: This is how C++ “perverted” the original Smalltalk design by changing it from message passing to make every call to an an object’s “methods” be simply shorthand for calling a function that took the object as a first parameter with a specific type. So, in C++ style the code dog.eat(food) is really Dog_eat(dog, food). This style is needed in C++ because C++ has pre-defined types that are enforced, so you can’t just whizz messages around without knowing the type of the receiver. To do that you need to turn every method call into a function to confirm the type. Python’s OOP is more like this.

This is one reason why I hate the word “method” since really in both of these cases an actual function is being called so the confusing use of some arbitrary specialization of “method” just adds more obfuscation layers to what’s going on. Really in both styles you’re causing a function to run. The only difference is in how you make it happen.

3 Likes

Thank you @zedshaw. That clarifies a lot for me. Not only when and how to use a function or a class but about OOP in general.
I have to read your post carefully again in the evening, because it’s a lot of information in it.

Thank.