Huh. Okay.
Huh. Okay.
Then I had to write a piece of software that heavily interacted with various bits of physical hardware, each with masses of state (serial communication and so forth). Suddenly the need for isolating state became terribly obvious. After seeing how some libraries did it, I wrote a class for every bit of hardware that abstracted the state away and provided a functional interface. It all worked terribly well, and it was a real lightbulb moment for me.
To be sure classes have a place and can be really useful, but so many people just create classes when they add no benefits.
Clear code always wins imho
Oh, and of course there's not one, but half a dozen power supplies. You could pass around the blobs of state seperately of course, but now you have to manage their scope independently from the functions that operate on them - a useless decoupling that adds overhead. What I ended up with was something like:
[psu.enable() for psu in psus]
Which you can always do, whenever psus is within scope. Hard to get terser and more idiomatic than that.
I know this because I wanted to do the same thing and have looked all over for a justification for it. In this case most people seem to agree that the bog standard for loop is the way to go:
for psu in psus:
psu.enable()
Some people (my boss) will even put it on a single line, so you don't lose much terseness.I think the rule of thumb is don't use a list comprehension unless you're going to use the list afterwards, else you're wasting an allocation.
I think the reason I instinctively write it this way is because in my mind, I basically think of list comprehensions as sugar for map + lambda. I'm "really" trying to write map(enable, psus). But of course, it's a method, so you need the instance[2] - map(lambda psu: psu.enable(), psus). The reason I prefer a map over a for loop is because it's a habit borne of the principle of least power - map provides a guarantee than no "funny business" (data dependency) is going on between the elements of the list you're iterating over. I scrupulously avoid for loops on principle, unless I need that kind of funny business. Of course in this case the for loop is so short as to make no difference, but like I say - it's a habit. In my code, "for" means "funny business here".
[1] not that it matters in this case - you're not toggling power supplies in a tight loop.
[2] Technically, in Python, map(psus[0].enable, psus) would work if psus was not empty. Or you could spawn a new instance: map(PSU().enable, psus). But ugh, talk about defeating the purpose.
This was quite useful for those of us who were bewildered by OOP.
When I learned Python, I was comfortable enough with using objects, that I had no problem creating classes.
So I think it's fair to say that creating classes is something that beginning Python programmers can put off.
Since I introduced Python to my workplace, I get to watch some fairly neophyte programmers develop their skills. These are typically engineers doing scientific programming, not commercial software developers. There's a point where I get to say: "You could put that stuff in a class." And later on, "You're creating too many classes." ;-)
> The Python Datamodel: When and how to write objects - https://www.youtube.com/watch?v=iGfggZqXmB0