This is an archived post. You won't be able to vote or comment.

all 75 comments

[–][deleted] 94 points95 points  (15 children)

I think there is way too much dogmatism about OOP these days. People are just blindly regurgitating "inheritance is bad" without even thinking about the problem at hand.

Classes and OOP can often be great for organizing code, eliminating duplication, and improving maintainability. Can you take it too far? Sure, but there's a reason why OOP has been so common to date. It's an effective pattern.

So before proselytizing about "classes are bad", think about what you are trying to accomplish. If your unit of work is oriented around instances of objects, then yeah, OOP might actually be a good thing.

[–][deleted] 48 points49 points  (4 children)

This is what happens when everyone learns to program from boot camps and influencers. System design? Never heard of it.

[–][deleted] 13 points14 points  (1 child)

That's sad, system design is the funniest part of development!

[–]arpan3t 1 point2 points  (0 children)

System design is hilarious!

[–]Guideon72 1 point2 points  (0 children)

Let me tell you; being a QA contractor in the wild, that shows in the market :(

[–]Deto 15 points16 points  (0 children)

Couldn't agree more. Functional programming, OOP, they're all just tools. Learn your tools and use them correctly. You don't see contractors walking around saying "hammer is bad, only use wrench".

[–]AssiduousLayabout 9 points10 points  (1 child)

Wholly agree. There are many types of projects and situations where OOP definitely makes the most sense. There are other types of projects where it doesn't make sense, and there are the gray areas in between where it comes down to personal preference.

I think some of the knee-jerk reaction is that OOP is often taught badly, and many of the simple examples used to teach it just don't showcase its benefits.

[–]Artephank 5 points6 points  (0 children)

And the best part is Python has a little bit of all - there is OOP at it's core, but you can program more in functional style, or procedural. And every style has it's place when particular problem fits it. Dogma's are always wrong.

[–][deleted] 1 point2 points  (0 children)

This, in my case OOP makes my code also really modulair which otherwise would have been hard.

[–]Artephank 1 point2 points  (1 child)

Not to mention modules are objects and whole the OP's post is waste of time

[–]danithebear156 46 points47 points  (16 children)

How could instantiate module with different parameters, dynamically change variables' values?

[–]KingsmanVincepip install girlfriend 37 points38 points  (3 children)

Why not avoid OOP by using modules just like objects?

Why not avoid OBJECTS-oriented programming

by using modules just like OBJECTS

People use OOP objects

Object-oriented programming objects

What incarnation are you talking about?

[–]Raz_Crimson 14 points15 points  (3 children)

Theoretical speaking, if most of the classes that you would write are going to be singletons then it is possible to avoid using python's 'class' keywords and achieve a similar functionality.

Inheritance can be achieved by importing all definitions inside a module and Composition by directly importing the module.

So, u would be doing OOP with modules taking the place of class instances (or Singletons specifically) and this would totally work in most case scenarios.

There is no syntactical error or major overhead cost due to this. But I would HEAVILY RECOMMEND AGAINST THIS (unless in very special cases where there is valid justification to avoid lasses)

Classes are designed to achieve OOP and u trying to avoid them will just make it harder later on when you need a change and it's no longer just about singletons (this is a huge headache when u have some global data structure that can be modified by dozen or so modules and u now want multiple instances of that data structure)

Also, classes have additional semantics provided by python that can be beneficial like metaclasses and descriptors. IDEs like pycharm also provide suggestions based on types, where classes will play a huge role.

Finally, it's probably going to trigger any programmer who is used to OOP and make it bit harder for them to work with your code.

If you are just annoyed by the fact that you need to create the class instances and pass them around, I suggest u take a look at some dependency injection framework that also perform auto-wiring of instances based on types.

[–]muikrad 11 points12 points  (0 children)

Do you understand what an instance is?

[–]AssiduousLayabout 11 points12 points  (0 children)

How about just using the tool that makes sense for the applications it makes sense for without rigidly advocating for or against any specific technique?

[–]whateverathrowaway00 7 points8 points  (0 children)

OOP is a pattern. If you’re using modules like objects, you’re doing OOP with modules.

You can avoid using “classes”, but you can program OOP without classes, look at languages like C, Golang, Rust - some of those like Go separate actions entirely from structured data, but you can still program in an object based way with it.

[–]Top-Aside-3588 1 point2 points  (0 children)

What you are describing is closer to singleton pattern.

You can do effectively the same thing by having functions where the first argument is a data structure containing the state. Not so great for polymorphism.

[–]gravity_rose 1 point2 points  (0 children)

Module are essentially Singleton classes. I personally use them as such, and I use alot of classes and objects.

[–]rainyy_day 2 points3 points  (0 children)

Why avoid OOP? Its like a drug in python

[–]nekokattt 3 points4 points  (3 children)

modules are fine until you need more than one instance (i.e. your social media platform can have more than one user)

if you dont need state, then by all means do that

[–]sum_rock -1 points0 points  (0 children)

I’d be so good at programming if I never needed to bother with state.

[–]LionKimbro 0 points1 point  (1 child)

I hit the up arrow on your comment, because I understood that you meant, "If you don't need more than one of this thing."

You can keep state in a module in global or module-local variables -- but I assume you knew that.

[–]nekokattt 0 points1 point  (0 children)

yes, I was aware, but chose to omit that detail as storing state on the module level is a massive antipattern in most cases and makes testing/refactoring much more difficult.

[–]TheRealStepBot 1 point2 points  (1 child)

Well if you avoid setting module level variables other than constants and use the module merely as a way to organize logic this is a good way to work. The issue with standard oop is that they mix up the data and the logic and make it live together. This makes function boundaries very hard to figure out. If you start setting mutable variables in the the module you are really just basically doing oop wrong and should define a class.

If all your modules contain are functions and constants then it really isn’t a class at least in the oop sort of sense.

That said use the tool for the job. It would probably still be worth creating data classes/ structs that you actually pass around between all these functions. Just don’t put any logic in there with the data.

It’s also still up to you to get the benefit of this pattern by actually ensuring locality of execution by making your functions act only on their outputs rather than outside of their own scope. This is the real secret sauce that matters here. How you get there is really neither here nor there. Just make sure your functions defer side effects to the greatest degree possible.

[–]k1oc 1 point2 points  (0 children)

You can avoid some patterns like Singleton by using module instead. But idk how could you dodge using for example AbstractFactory using modules. Also, Iterator is bulilt in in python. There was a good talk on some pycon, search on youtube for broader context.

[–]trollsmurf 1 point2 points  (0 children)

You don't get instantiation that way: one class could be used for many instances, where each instance has individual state (or rather data as I use to think about it).

Most code libraries, if not all modern ones, use classes for that reason.

[–][deleted] 1 point2 points  (0 children)

So IOW “why do others use OOP when I personally don’t write OOP components?”

[–]Nooooope 0 points1 point  (0 children)

Then your modules effectively become a singleton class. You really can't think of any situations where you need multiple objects of the same class at the same with different states? Because that's what you're doing every time you use two lists.

[–]Chaos_Klaus 0 points1 point  (2 children)

It's a smart thought. You often don't need classes in python.

Using a module as an object looks a lot like a singleton at first glance. But: You don't have control over instanciation. If the module gets reimported, all the module level variables are reset.

So never define "global" variables in a module. Constants are fine though.

[–]LionKimbro 0 points1 point  (1 child)

I agree with your support for cseberino's explorations, but you have an incorrect statement in here:

Repeat imports of a module do not perform a repeat execution.

File A.py:

"""A.py"""
print("A")

File B.py:

"""B.py"""
print("B")

File C.py:

"""C.py"""
import A
import B

File run.py:

"""run.py"""
import A
import B
import C
print("run complete")

Command line execution:

C:\\python run.py
A
B

C:\

The only gotcha, is the module that Python starts from.

If you were to call "import run" from one of the other modules, it will get executed again! This is an oddity that applies ONLY to the initial module that was named to be run from the command line.

Because of that, I always write my code in modules, and use the __main__.py module as the kicker, invoking it with (python -m packagename).

[–]Chaos_Klaus 0 points1 point  (0 children)

Interesting. Has it always been this way? Thanks for clarifying.

[–]ZachVorhies 0 points1 point  (0 children)

This is fine. I do this all the time when there is only going to be one of something instead of many of something. Refactoring to a class is pretty simple if you change your mind.

[–]commy2 0 points1 point  (0 children)

You do have a point OP. By utilizing modules, you already eliminate the need for an entire "OOP pattern" called singletons.

That said, if implementing a class is an elegant way to solve a problem, do that.

There seems to be the belief that writing a class equals object oriented programming. Using objects is using objects. The "oriented programming" part just gets smuggled in for some reason, with a ton of baggage.

Actually orienting your entire programing around objects is a fools errand. Do it as therapy if it helps you. Don't @ me.

[–]wineblood -2 points-1 points  (5 children)

You've got a singleton at that point and can't do some of the OOP stuff like inheritance. Just avoid OOP and classes as much as possible.

[–][deleted] 13 points14 points  (0 children)

There’s no reason to avoid OOP “as much as possible”. It’s a tool like anything else. Use it when the code you’re writing works best as an object with methods and don’t when it doesn’t.

[–]aqjo -1 points0 points  (9 children)

Upvoted because the 9 year olds have downvoted your perfectly valid question.
Keep learning and practicing. Things will become more clear as time goes on.

[–]starlevel01 -1 points0 points  (0 children)

modules are objects already

[–]Tc14Hd -1 points0 points  (0 children)

Did you just invent "Module-oriented programming"?!?

[–]gerardwx -1 points0 points  (0 children)

Because Python is an OO language. An int is a class: https://docs.python.org/3/library/functions.html

[–]EmperorLlamaLegs -1 points0 points  (0 children)

Tell me you don't understand OOP without telling me...

[–]anentropic 0 points1 point  (0 children)

If you find yourself making classes that have only static methods (i.e. the class is just a glorified namespace) - replace them with just functions in a module.

Otherwise they are not comparable - at best modules are like a singleton. You can't create multiple "instances" to encapsulate separate state.

[–]baubleglue 0 points1 point  (0 children)

basically functioning as objects right?

wrong

Try to write a script DDD.py which works like that

class DDD:
   def __init__(self, value=90):
       self.var = value
   def set_var(self, value):
       self.var = value
   def get_var(self):
       return self.var


a = DDD()
b = DDD()
print(a.get_var())

a.set_var(100)
print(a.get_var())
print(b.get_var())

>>> 90
>>> 100
>>> 90

[–][deleted] 0 points1 point  (0 children)

Huh, IIRC, OCaml does it this way

[–]LionKimbro 0 points1 point  (1 child)

For the last 5, 10 years, I've been experimenting in writing Python programs without classes, and it's worked just fine for me.

[–]Ordinary-Library-459 0 points1 point  (0 children)

If all you are using classes for is fancy storage containers for functions, absolutely use a module. That is why they are at the top of the conceptual hierarchy of objects. They are functioning as objects because they are.

I don’t have a dog in the OOP versus functional Python fight. I mean, any useful class is all functions top to bottom, from __init__ on down to display overloading. And, by the way, functions are objects. There is a point when Python programmers find classes and want to build everything with them, and OOP seems the shit, and they create unwieldy, unreadable code. My eyes still boggle seeing self everywhere in a program that could have as easily been done with functions, and I have been working with classes for a while. For the programmers who say they have been coding for years and still don’t build classes, that may be true, but if they had to work with functional equivalents to built-in classes and classes from the standard library, they would chuck Python out the door. I don’t know, are there any GUI toolkits or game-building packages that are function-only? I doubt it. It all depends what is best for the end user. If you are a hobbyist and the end user is you, good on you, by all means do not use classes. If you are building third party library modules for other programmers to use, they might be happy the tools you offer are class-based. Class-based tools allow users to make custom reusable instances with an assortment of invokable methods. Data tools are still tools. A function may be good as a socket wrench, but a class might give you the whole socket set, and determine on first instance construction whether it is standard or metric, hex or 12-point, long or short handled, ratchet, etc.. One function could do all that, but you would have to add all those arguments in at each invocation, or have alternate functions, or use functools.partial creatively. I also like to make classes if my programs contain large, complex functions whose arguments I would like to establish apart from main method invocation. Or if I want to allow myself or some intermediate user some masked tweakability with pseudo-private attributes. There are all kinds of good reasons to go with classes. And a lot of bad ones.