5 ms·
These are minor annoyances to me. The major annoyance I have with Python is that most Python code makes such heavy use of classes, even when it only needs lists
by kyllo 7y ago
These are minor annoyances to me. The major annoyance I have with Python is that most Python code makes such heavy use of classes, even when it only needs lists, tuples, and dicts.
Why do I really need a class, when:
- Instance fields can be added and removed at runtime
- Private fields and methods are not actually private ("we're all consenting adults here")
- No pattern matching on types and `if isinstance(foo, Bar):` is an anti-pattern because it's a duck-typed language
- Interfaces are neither available nor necessary due to late binding. Abstract Base Classes are the closest thing to an interface, but they're also unnecessary because again, it's duck-typed.
- Inheritance is widely considered to be a mistake ("Prefer composition over inheritance" etc)
- Classes tend to complicate testing
I can use classes to write custom data structures, I guess, but in a language as high-level as Python, I can just model trees and graphs with dicts. If I need a more performant data structure, I'm not writing it in Python in the first place.
I've seen some very experienced Pythonistas recommend using namedtuple instead of classes for most use cases, and I tend to agree with them. That gets you immutability as well as dot notation for accessing fields.
Clojure programmers seem perfectly happy with just lists and maps, and after experiencing that, classes feel like a bolted-on misfeature in Python.
- Scarblac 7y agoYou can even subclass namedtuples to get immutable value objects with helpful methods. I like classes over dictionaries because I can look at the class definition to see what the variables my function gets are, and what functions (methods) exist to work with them. I used to work with a code base that passed dictionaries around, and there were a lot of hacks where people had some data somewhere that they needed somewhere else, and the dict was available both places, so why not add it to that... Different pieces of code added different things and you were never quite sure which version of the data was passed this time for the "layers" parameter. Somehow it doesn't happen as much with classes. It was like duck typing to the extreme. I call it smurf typing, if it smurfs like a smurf, smurfs like a smurf and smurfs like a smurf, nobody knows what's going on anymore. Immutable value classes, those are good.
- j88439h84 7y agoMy solution to this is http://attrs.org http://attrs.org or dataclasses. They make a huge difference in readability and type safety.
- siddboots 7y agoI feel like PEP557 missed an opportunity when it named data classes. The syntax is such an improvement that there is very little reason not to use them over ordinary classes for most purposes.
- j88439h84 7y agoPython probably should've just used attrs directly, like it does with setuptools, rather than making a whole new package.
- dragonwriter 7y ago> Why do I really need a class, Among other cases, you need a class where natural, convenient, consumer-friendly use of a data structure should leverage features like operators and standard protocols that rely on the existence of particular methods (often special methods.) > If I need a more performant data structure, I'm not writing it in Python in the first place. While Python is linearly slow, that’s no excuse to use data structures with poor big-O performance (small n may be, but that's no more or less true of Python than of a more performant language.) > I've seen some very experienced Pythonistas recommend using namedtuple instead of classes for most use cases Namedtuple is just a function that returns a fresh class; you can't use “namedtuple instead of classes”, as it's a convenience mechanism for creating a class with certain commonly-useful features. > Clojure programmers seem perfectly happy with just lists and maps And vectors. And sets. And records. And a bunch of other common data structures. But, yes, the use of multimethods for type-based dispatch that clojure uses replaces classes. But Python doesn't have multimethods built-in and the core language and stdlib don't use them (they are available in a non-standard library).
- kyllo 7y ago> you need a class where natural, convenient, consumer-friendly use of a data structure should leverage features like operators and standard protocols that rely on the existence of particular methods (often special methods.) I understand and I can't disagree, this just seems much, much narrower in scope than what classes are used for in typical Python code I see every day. Which is perhaps due to influence from other languages like Java/C++ etc.
- sebastos 7y agoIsn't the reason to use classes the dispatch aspect of it? If I take in a duck-typed object and call obj.foo(), then I get an appropriate class-specific version of foo(). Like you said, isinstance() is an anti-pattern - I don't want to define a function that behaves differently based on explicit testing of input type, because that wrecks the duck typing. Right?
- kyllo 7y agoYes, exactly. Nail on the head. When I do have a datatype that needs to be handled differently based on some condition, I tend to use ABC's with only one level of concrete subclasses, just to make that implicit method interface explicit.
- ummonk 7y agoYeah namedtuple is the standard thing now but it is much heavier and boilerplatey compared to e.g. a struct in Typescript.