10 Python Anti-Patterns That Are Breaking Your Code

preview_player
Показать описание

Think your Python code is clean? Think again. In this video, I’m exposing 10 Python anti-patterns that look smart, but secretly create chaos. Stick around to see if you’re guilty of any… I know I was.

🔖 Chapters:
0:00 Intro
0:26 Using Exceptions for Control Flow
4:06 Using Classes with Only Static Methods Instead of Modules
5:15 Overriding Dunder Methods in Surprising Ways
9:33 Hardcoded Values Throughout Your Code
13:54 Writing Custom Decorators Just to Inject Stuff
15:57 Over-Engineering with Design Patterns You Don’t Need
19:00 Inappropriate Intimacy
20:39 Not Using Abstraction
23:14 Importing Everything with a Wildcard
24:15 Not Using Built-in Tools and Libraries
24:51 Final Thoughts

#arjancodes #softwaredesign #python
Рекомендации по теме
Комментарии
Автор

Yes I would like the "just use a function" shirt. Will you be making a merch shop for them?

sillybuttons
Автор

Exceptions are actually pretty cheap now in newer python versions. If raising an exception or returning status codes is the right path depends on the context imho.

SuperGrimmy
Автор

I recommend this channel to everyone ! btw, you haven't seen antipatterns until your colleagues start reading their own custom module as text and using "exec" on it because they don't know how the import system works + code that is executed on import + everything in mutable global variables.

paper_cut
Автор

For the case of overriding dunder methods where you select a class to return: You can use __init_subclass__ to register all your various subclasses and make a classmethod that automatically selects the right class for you, based on arbitrary conditions/something you pass. Very clean factory pattern imo.

realms
Автор

I’ve been following your channel for several years now, and I’m thrilled to see how you’re now using simple functions instead of objects. Your early videos were very OOP-oriented, and I learned a lot about that thanks to you. But all-objects-all-the-time isn’t very Pythonic.
At work, I had to take over a Python project written by a Java developer, and it was a nightmare for me.

jcurwen
Автор

8:25 Small note: Use “is” with Enums instead of “==“.

stokhosursus
Автор

Not sure I agree with the exception handling as control flow bit.

Exceptions being expensive performance-wise.. I'd say that depends on the application. If you're calling an API, the time penalty of catching a timeout exception Is probably negligible in comparison with the time of using the network. Applications should be benchmarked to detect performance bottlenecks.

About code becoming a mess... Maybe but I don't think that was clear from the chosen example.
I'd say raising exceptions on the error cases has the advantage that the return type can be simpler in the happy path. This was kind of obscured in this example by the fact that dict[str, str] was used.

er
Автор

I would genuinely love a just use functions sticker, take my money

jrheard
Автор

Perhaps ironically, the example for the "don't override dunder methods in unexpected ways" is exactly how pathlib implements support for different OSs: pathlib.Path.__new__ will return instances of different types depending on the OS it's running.

tonny_dourado
Автор

Python is built around control flow with exceptions. The canonical example is loops are exited with an exception. Turning everything into an optional or status type and constantly checking the return values starts to look an awful lot like exception catching without the ergonomics of being able to bubble up exceptions up the stack. I've had code reviews where a junior is trying to to write python like go and it just becomes awkward, plus most 3p libraries are built around an exception model. Really the best I've seen is to offer a `raise` method along with status returns so the user of you library API can choose what they want.

kdaubtf
Автор

I haven't finished watching this video yet, but I stopped at your idea "Just use functions" and you know, it's a good idea, because something similar is done by the author on the Learn Linux TV channel 😃 It's time for you to release your own brand with interesting phrases and conclusions 😃

MrVernuk
Автор

Incredibly useful video (and I agree with all recommendations here). Thank you Arjan.

davorbokun
Автор

"Just use functions" - Yes! I'm always promoting this. There is sooo much overengineered code based on patters from other languages that need to use classes. This is Python, not Java or C++, people come with their foreign habits and spread them around, poisoning the pythonic simplicity.

piotrjasielski
Автор

I will buy a shirt that says "Just use functions"

kodonryati
Автор

8:22 Enums can be used like hashmaps (dicts). So you can create a variant by simply doing "PaymentMethod[payment_type]" without if-elif-else block. If there is no such variant - KeyError. And I found it useful to create a `try_from_str(cls, key: str)` classmethod to implement different logic. Maybe, you want to upper keys... But, honestly, it's useful only in kinds of parsing URL params and CLI tools. Because in highly typed code you don't really want to let some unknown string to control flow of your code, so the use scope is limited to parsing, I guess.

ЕвгенийКрасилов-оо
Автор

Great, I agree with everything, the main point is not to complicate things unnecessarily, optimized and concise code is very valuable, and code with subtraction of the sum of numbers through class methods and a dozen imports and AI will be able to give. Thanks for the useful video!

Extrey
Автор

I like the idea of a just use function t-shirt 😅

Marc-ElianBegin
Автор

Thank you, simple is better than complex!

JonitoFischer
Автор

@ArjanCodes at 7:17 I would argue that you can apply Factory for Payment along with Singleton... or Abstract factory correctly. But it would still need to be a bit different from example given on the video.

eduferreyraok
Автор

Hard disagree with points 6, 7, and 8
- The final solution requires that we have a dictionary with all export formats. Adding a new format requires changing existing code.
- The `Report` class is now coupled to the export format. Every time we add a new format we need to update the class. What if the class is not under our control?
- The `Exporter` class is larger than it needs to be according to the consumers. For example, the `export_to_csv` function requires a `report: Exportable` which provides not only `to_csv` but also `to_json`. Why would the CSV exporter require something that can be converted to JSON?

There are other comments addressing the usage of exceptions for control flow. I have to agree with them too: using `error` results is terrible in Python and one of the worst things Go has brought back to the mainstream.

valcron-
welcome to shbcf.ru