[HN Gopher] Python Design Patterns (2018)
___________________________________________________________________
Python Design Patterns (2018)
Author : luu
Score : 219 points
Date : 2022-03-12 06:43 UTC (1 days ago)
(HTM) web link (python-patterns.guide)
(TXT) w3m dump (python-patterns.guide)
| simulo wrote:
| Nice! I just looked at it yesterday when I was collecting
| resources on architecture of WebApps in python. I found that
| Refactoring guru also has python examples for them pattern
| section.
| brumar wrote:
| This is my favorite ressource on the subject. I recommend it as
| often as possible.
| rmbyrro wrote:
| Some of these patterns have proved to be really powerful in real-
| world projects.
|
| One challenge is having them fresh on my mind and being able to
| spot when it makes sense to apply them.
|
| Have been thinking about using flashcards and spaced repetition
| to achieve better retention and ability to apply in practice.
|
| Anyone has experience with this?
| blt wrote:
| Use good libraries and pay attention to what makes them
| appealing. Large programs should usually be structured as a
| collection of libraries. When you are designing an API for your
| own libraries, think back to how other libraries solved similar
| problems at the API level. Many (most?) worthwhile design
| patterns can then be derived from scratch as a way to achieve a
| particular API structure.
| brumar wrote:
| As others wrote, in depth practice is a sensible choice. Once
| it's done, I believe spaced repetition is a nice insurance
| against memory fading and can be as simple as a few big cards
| listing the concepts learned even if that's really not what
| spaced repetition proponent would suggest.
| travisjungroth wrote:
| Insanely powerful and underutilized technique: write a list of
| techniques you can apply (in this case, patterns). Just write
| the names, you want this to be dense. When you have a choice to
| make, look at the list. It doesn't take long to scan 12 names.
| nerdponx wrote:
| My experience is that worked, traditional textbook-style
| exercises are the best way to learn and internalize this kind
| of knowledge. A combination of shorter exercises with longer
| open-ended tasks is good. Basically more or less what you'd get
| on a homework problem set in a university course.
|
| Maybe the fact that this kind of work ends up being "spaced
| repetition" in some sense is part of why it's helpful.
| kaycebasques wrote:
| Maybe work from the other direction? Work through each pattern
| and think about where they might work in your existing
| codebases and then try implementing them just for the sake of
| hands-on experience.
| simulo wrote:
| I made the experience that they are hard to learn and
| understand out of context, so practicing on flashcards does not
| make much sense for me. What I did is programming some mini
| projects in which one or two patterns are used: Pub-sub is nice
| in anything UI related, commands+state is great for a simple
| undo/redo-manager etc.
| ThePhysicist wrote:
| If you're interested in Python anti-patterns instead, we wrote an
| open-source book on them a while ago:
| https://docs.quantifiedcode.com/python-anti-patterns/
|
| Hasn't received any updates in the last years but it still holds
| up quite well, disregarding the Python 2 specific anti-patterns
| of course which become less and less relevant, as well as the
| Django-specific ones, which probably are hopelessly outdated.
| IshKebab wrote:
| Not a bad list. Feels like most of them should just be linter
| rules. I also found a few them don't really apply if you're
| using static types (which you really really really should),
| e.g.
|
| * Returning more than one variable type from function call:
| That's fine; the type checker will make sure you don't make a
| mistake.
|
| * Asking for permission instead of forgiveness: Makes sense for
| the example given (`unlink`) but it is better to e.g. check
| types explicitly with `isinstance()` than to catch `TypeError`.
| ThePhysicist wrote:
| Yes absolutely, that book was written before type annotations
| made it into Python though.
| sgt wrote:
| Not idiomatic Python. Don't model your best practices in Python
| based on what makes sense in e.g. C++ and Java.
| munro wrote:
| 100000%, Python is really excelling at functional programming
| these days. With dataclasses & typing we now effectively have
| GADTs. Every few months I'm noticing small functional
| improvements, and I'm loving it! Even though it says `class`, I
| use it for GADTs, Protocols, and eDSLs--and it feels very
| idiomatic. These are the 'patterns' you see in SQLAlchemy, jax,
| pytorch.
| nuclearnice1 wrote:
| Interesting stuff! What are the sources to learn more?
| chapium wrote:
| I feel a bit contrarian about design pattern lists. These always
| seem to contain a list of solutions and after some fancy
| gymnastics, a list of potential problems they might solve. I feel
| it might be more useful to create a list of common software
| problems and follow them with a pattern that helps solve the
| problem. I think this would help address the issue of these
| pattern guides being applied overzealously.
| xtiansimon wrote:
| Cookbook?
| syntaxfree wrote:
| Pattern clusters would be better. Like "... so you want to
| design a programming language, this is the Visitor pattern, the
| Dispatch..."
| [deleted]
| rochak wrote:
| Well, this post turned out to be a gem. Loved it.
| ericls wrote:
| I don't like these content about programming. Why listing a bunch
| possible of answers to some solved problems instead of try to
| dive deep into the problem themselves.
|
| This feels like encouraging people to buy a bunch of cameras
| instead of teaching people how to take good photos.
|
| A good solution may end up looking like some patterns, but
| sourcing good solutions from a pool of patterns is impossible
| unless the problem you are trying to solve is the exact same as
| the one a pattern is solving, in the same environment and
| context.
|
| I do find the content can be very useful for many, but can we not
| call them patterns?
| nooorofe wrote:
| > Python Design Patterns
|
| My brain puts it next to: globe of China, Jewish Olympic games
| (real thing).
| rr808 wrote:
| This is great. I always thought that GoF patterns is largely
| obsolete in 2022, it would be nice if the author agreed and has a
| list of GoF patterns that really dont make sense any more.
| Builder was one I thought should be included but OP seems to
| think its relevant (though different).
| jerf wrote:
| In terms of obsolete GoF patterns, Flyweight is my nomination.
| It's not that it's useless, is just that in an era of 64 MB of
| RAM, it makes sense that people might need to know about it,
| but in an era of 64 GB of RAM the need is diminished to the
| point that only the people who have those problems need to
| worry about it.
|
| And if you _do_ have those problems, it isn 't even necessarily
| what you would reach for first. Though it's at least on the
| list.
| hcrisp wrote:
| Luciano Ramalho in his book "Fluent Python" mentioned that some
| (most?) of the GoF patterns are unneeded in a dynamic language
| like Python. I see [0] he is favorable to this site's author,
| so it is probably worth a look.
|
| [0]
| https://twitter.com/ramalhoorg/status/960746929025142784?s=2...
| polynomial wrote:
| How did you happen to see that? That tweet is perfectly
| relevant, it's byond _uncanny_ that you had it at the ready.
| hcrisp wrote:
| Coincidence. I was trying to find the reference to
| Ramalho's comment about GoF and found his comment in a
| random search.
| stingraycharles wrote:
| Interesting, thanks for sharing. Is the opposite also true,
| that when a language is statically typed, design patterns are
| likely to be needed?
| javcasas wrote:
| It depends on the language expresiveness, not on it being
| static/dynamic types. Dynamic languages tend to have less
| limitations to expresiveness (no typechecker in the middle)
| and then you have programming languages with static types
| and decent typecheckers that don't require design patterns
| because they are still very expressive.
| hcrisp wrote:
| I found the quote. He says Peter Norvig wrote that "16 out of
| 23 patterns have qualitatively simpler implementation in Lisp
| or Dylan than in C++ for at least some uses of each pattern"
| and that Python shares some of the dynamic features of these
| languages such as first-class functions. I wonder if making
| GoF patterns simpler or even "invisible" in C++ using
| functions or callable-objects is implicitly not allowed
| because of the static typing of the language or if it just
| wasn't considered by the authors.
| javcasas wrote:
| Most of the design patterns exist because of limitations in
| programming languages, especially java/c++/c#. The strategy
| pattern disappears when you can store functions in data
| structures. The abstract factory pattern disappears when you
| can pass functions as parameters. The builder pattern
| disappears when your progamming language has named
| parameters. The observer pattern is callbacks with additional
| steps. The mediator pattern disappears with support on
| variants of functional reactive programming. The iterator
| pattern disappears by using your favourite version of
| generators (or just go hardcore like Haskell and do
| foldable/traversable).
|
| IMO GoF has been obsolete for the last 20 years (50 years if
| you consider that languages like ML, Lisp and friends already
| existed then).
| happymellon wrote:
| Builder patterns work very well for generation of templates. I
| use them a fair amount when dealing with Amazon's CDK as it
| helps with fixing a lot of readability issues.
|
| I see people claim that GoF patterns are obsolete, and that
| builder is one of the ones that are old hat, but for making
| configurations readable it can be the best solution.
| javcasas wrote:
| What's the advantage of:
|
| t = TemplateBuilder() .withFoo(foo) .withBar(bar)
| .excludeBaz() .build()
|
| over:
|
| t = Template(foo=foo, bar=bar, baz=none)
| culturedsystems wrote:
| I agree there's not much point using this kind of simple
| builder if you have named function parameters, but the GoF
| builder pattern has a couple of additional features which
| can still be useful. In the GoF examples the construction
| process is more complicated (maybe the order in which
| construction steps take place is significant, and maybe
| parts of the construction might be conditional), and the
| same construction algorithm can be used to produce
| different types of object. If I remember correctly, the
| main example in the GoF book is a builder for creating
| documents by adding a title, subtitle, paragraphs, etc, and
| the document being constructed might be a UI
| representation, an RTF file, HTML, etc.
| musha68k wrote:
| I know python (3) is an object oriented programming language by
| design but none the less I was wondering if some "functional"
| pythonista's had recommendations on some good "less (oop) is
| more" patterns to share in here?
| oroul wrote:
| It's hard to completely get away from objects in Python, but I
| don't think that needs to be an objective to get away from OOP
| patterns. My suggestions would be:
|
| - Don't use classes for information. Use regular data
| structures (dict, list, tuple, set) and use functions to
| manipulate them. If you really want/need something like a
| struct, use a dataclass.
|
| - The itertools module has a bunch of useful constructs for
| creating and combining iterators. Take advantage of Python's
| iterators and construct your own when necessary.
|
| - List comprehensions and generator expressions are great for
| clear and concise data transformations
|
| - You're going to have to deal with state somewhere in your
| program. That's fine, some state is necessary to do real work.
| Don't feel bad about creating classes for things like context
| managers (e.g. for a database connection) so you can use it in
| a with statement and it will handle the setup and teardown
| logic for you. That way your business logic stays concise and
| Pythonic since those classes can be in separate modules and
| imported as necessary. I've found this 'functions in the front,
| classes in the back' approach to writing Python useful as it
| lets me think about what my program does in a functional manner
| without denying myself the ergonomics of Python's class-based
| ecosystem.
| javcasas wrote:
| Scrap all the factories. The class name is also a function and
| a constructor. Just pass it around as parameter, and bypass all
| the factory stuff.
|
| Use named parameters and bypass the builder pattern.
|
| Store operations in objects/lists. Bypass the strategy patterns
| with this knowledge. Did you know myobject.mymethod is a
| function, and you can do x = myobject.mymethod, and then x()?
| Store methods in lists, pass them as parameters, partially-
| apply parameters to them.
|
| Generators are more than what the iterator pattern will never
| be.
| qbasic_forever wrote:
| Learn Go and spend some time in its world, then come back to
| Python IMHO. You'll start to appreciate the subset of Python
| that's just functions at the module and class level and ignore
| all the complexities of metaprogramming, class hierarchies,
| etc. You'll find a lot of folks using Go are coming from Python
| and burnt out on big, complex codebases there--the simplicity
| and "less is more" is a breath of fresh air to reapply to
| Python.
| ElevenPhonons wrote:
| https://github.com/mpkocher/Functional-Programming-Technique...
|
| I covered a few core concepts (e.g., functions as first-class
| citizens, closures, partial application, etc...) and added a
| few real world examples of using a functional centric design.
| The text/format has some rough edges, but overall I think the
| text is useful for internalizing how to leverage a functional-
| ish approach.
|
| Other resources.
|
| https://github.com/sfermigier/awesome-functional-python
| klysm wrote:
| In my experience, developers that reach for design patterns
| recently read a design patterns book and are desperate to apply
| them to problems, instead of trying to figure out the best
| solution to the problem. Design patterns (imo) should be used to
| get a feel for the design space that you can choose from, but
| it's far from a total enumeration.
| MaxMoney wrote:
| carapace wrote:
| FWIW, if you really want to understand Pattern Language you
| should go and read the source material: Christopher Alexander's
| book of the same name and it's companion volumes. The GoF did a
| fine job, but there's a richer and deeper constellation of ideas
| and philosophy and design strategies in the original material.
|
| - - - -
|
| In re: Singleton pattern in Python: one interesting technique is
| to use a module as a singleton. When client modules "import
| singlefoo" the first import caches the module object (in the
| sys.modules dict) and subsequent imports use it: presto!
| Singleton!
___________________________________________________________________
(page generated 2022-03-13 23:00 UTC)