News for hackers. Stuff that matters.
Re:Python Design Patterns (2018) by musha68k on Sunday March 13, 2022 @04:01PM (#30665143)
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?
Re:Python Design Patterns (2018) by oroul on Sunday March 13, 2022 @04:47PM (#30665534)
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.

Re:Python Design Patterns (2018) by tikhonj on Sunday March 13, 2022 @09:26PM (#30667547)
> Don't use classes for information. Use regular data structures (dict, list, tuple, set) and use functions to manipulate them.

I've written a lot of functionalish Python, and I've found that this is a consistent way to breed code that's hard to understand. Instead, I would default to (usually frozen) dataclasses to represent data—they're functional records that also let your code reflect the concepts that make sense for whatever you're doing. A list of dictionaries of strings looks like any other list of dictionaries of strings; a sequence of User objects has clear semantics and, as a benefit, is harder to mutate in unexpected ways.

Re:Python Design Patterns (2018) by bruh2 on Monday March 14, 2022 @05:18PM (#30678467)
Wouldn't TypedDict come in handy here? This way we can kinda mimick a structural typing system. The only disadvantage I ran across here is that TypedDict can't handle recursive fields, unlike dataclasses. Otherwise, it seems to me like a more Pythonic choice, reminding of Clojure
Re:Python Design Patterns (2018) by rmbyrro on Sunday March 13, 2022 @08:33PM (#30667249)
> Don't use classes for information. Use regular data structures (dict, list, tuple, set) and use functions to manipulate them.

One problem is many of these datastructures are easy to mutate. When I need to ensure immutability to a dictionary, for instance - quite often - I can't avoid wrapping it in a class and setting up an interface to lock down mutation.

If Python had a way to declare immutable datastructure, similarly to Clojure, it would make life a lot easier...

Re:Python Design Patterns (2018) by galoisscobi on Sunday March 13, 2022 @09:19PM (#30667506)
Frozen dataclass instances (https://docs.python.org/3/library/dataclasses.html#frozen-in...) might be of help.
Re:Python Design Patterns (2018) by rmbyrro on Monday March 14, 2022 @04:13AM (#30669683)
Wasn't aware of this feature in dataclasses, that can be helpful in a few cases, thanks for pointing out
Re:Python Design Patterns (2018) by ciupicri on Sunday March 13, 2022 @09:37PM (#30667606)
> class types.MappingProxyType(mapping)

> Read-only proxy of a mapping. It provides a dynamic view on the mapping’s entries, which means that when the mapping changes, the view reflects these changes.

https://docs.python.org/3/library/types.html#types.MappingPr...

Re:Python Design Patterns (2018) by rmbyrro on Monday March 14, 2022 @03:55AM (#30669579)
This can be helpful in some cases, but it's precisely what I sometimes need to avoid, which is protecting a dictionary and having changes affecting only its own scope.

If function A passes a dict to function B, I would like:

1) Function A to keep the dict intact while function B can manipulate its content;

2) Function A can change the dict after passing to B, and B still keep the original copy, unaware of A's later changes.

One way of doing this is by deep copying dictionaries around, but it can easily become a big performance issue.

Re:Python Design Patterns (2018) by ciupicri on Monday March 14, 2022 @03:11PM (#30676818)
It sounds like what you really want is an efficient way of copying dictionaries, perhaps copy on write, something like the cowdict [1] project.

[1]: https://pypi.org/project/cowdict/

Re:Python Design Patterns (2018) by blunte on Sunday March 13, 2022 @07:15PM (#30666732)
Can you point to any public codebases which illustrate this approach in Python? I would love to see some of these principles in action.
Re:Python Design Patterns (2018) by javcasas on Sunday March 13, 2022 @04:48PM (#30665545)
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.

Re:Python Design Patterns (2018) by ElevenPhonons on Sunday March 13, 2022 @04:37PM (#30665458)
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

Re:Python Design Patterns (2018) by qbasic_forever on Sunday March 13, 2022 @06:22PM (#30666330)
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.