[HN Gopher] Lesser known parts of Python standard library
___________________________________________________________________
Lesser known parts of Python standard library
Author : rbanffy
Score : 191 points
Date : 2024-09-04 21:07 UTC (1 days ago)
(HTM) web link (www.trickster.dev)
(TXT) w3m dump (www.trickster.dev)
| brianyu8 wrote:
| If you liked this blog post, I can't recommend PyMOTW[0] highly
| enough. It's my goto for a concise introduction whenever I need
| to pick up a new Python stdlib module.
|
| [0]: https://pymotw.com/3/
| judicious wrote:
| I find defaultdict, OrderedDict, namedtuple among other data
| structures/classes in the collections module to be incredibly
| useful.
|
| Another module that's packaged with the stdlib that's immensely
| useful is itertools. I especially find takewhile, cycle, and
| chain to be incredibly useful building blocks for list-related
| functions. I highly recommend a quick read.
|
| EDIT: functools is also great! Fantastic module for higher-order
| functions on callable objects.
|
| https://docs.python.org/3/library/itertools.html
| padthai wrote:
| Why do you use OrderedDict for now that regular dicts are
| ordered by default?
| judicious wrote:
| I work with different versions of Python3 (and 2
| unfortunately) and some code is still in 3.6, hence I used
| OrderedDicts.
| mixmastamyk wrote:
| 3.6 was the first with the new ordered by default dicts,
| even though wasn't specc'd until 3.7.
| Izkata wrote:
| It worked as an accidental implementation detail in
| CPython from some other optimization, but it wasn't
| intentional at the time. Because it wasn't intentional
| and wasn't part of the spec, that code could be
| incompatible with other interpreters like pypy or jython.
| ericvsmith wrote:
| See my comment and the linked email at
| https://github.com/ericvsmith/dataclasses?tab=readme-ov-
| file... for dataclasses and 3.6. I think it's still true.
| raymondh wrote:
| The reason Guido didn't want 3.6 to guarantee dict
| ordering was to protect 3.5 projects from mysteriously
| failing when using code that implicitly relied on 3.6
| behaviors (for example, cutting and pasting a snippet
| from StackOverflow).
|
| He thought that one cycle of "no ordering assumptions"
| would give a smoother transition. All 3.6 implementations
| would have dict ordering, but it was safer to not have
| people rely on it right away.
| masklinn wrote:
| pypy implemented naturally ordered dict before cpython
| did.
|
| jython never released a P3 version so is irrelevant,
| ironpython has yet to progress beyond 3.4 so is also
| irrelevant.
| sgarland wrote:
| As someone who just had to backport a fairly large script
| to support 3.6, I found myself surprised at how much had
| changed. Dataclasses? Nope. `__future__.annotations`? Nope.
| `namedtuple.defaults`? Nope.
|
| It's also been frustrating with the lack of tooling
| support. I mean, I get it - it's hideously EOL'd - but I
| can't use Poetry, uv, pytest... at least it still has type
| hints.
| neves wrote:
| Not even VSCode extension works anymore
| heavyset_go wrote:
| OrderedDicts have some convenience methods and features that
| ordinary dicts don't have.
| rbanffy wrote:
| Also, dicts can become unordered at any time in the future.
| Right now the OrderedDict implementation is a thin layer
| over dict, but there are no guarantees it'll always be
| that.
| wodenokoto wrote:
| They can, but ordered dict can also become unordered in
| the future, should the steering committee decide.
|
| But seriously: It's no longer an implementation detail
| that dictionaries are ordered in Python. It's a
| specification of how Python works.
| rbanffy wrote:
| I missed that in the 3.7 release notes.
| judicious wrote:
| There in lies another reason why OrderedDicts are still
| useful even in 3.12
| rbanffy wrote:
| Not really. It was pointed out that since 3.7 the order
| preserving behaviour is part of the spec for dicts.
| judicious wrote:
| I guess for most purposes, OrderedDicts are then
| obsolete, but I believe there are some extra convenience
| methods that they have, but I've only really needed to
| preserve order.
|
| Makes you think what other parts of Python have become
| obsolete.
| 3eb7988a1663 wrote:
| Not true as of 3.7[0] the insertion-order
| preservation nature of dict objects has been declared to
| be an official part of the Python language spec.
|
| [0] https://docs.python.org/3.7/whatsnew/3.7.html
| rbanffy wrote:
| Oh well... This is what I get to not look at release
| notes with lawyer eyes. Thanks for the correction.
| SuchAnonMuchWow wrote:
| dict are ordered to keep argument order when using named
| arguments in function calling. So it would be a non-
| trivial breaking change to revert this now.
|
| I would argue that OrderedDict have more chances to be
| depreciated than dict becoming unordered again, since
| there is now little value to keep OrderedDict around now
| (and the methods currently specific to UnorderedDict
| could be added to dict).
| wodenokoto wrote:
| Do you have any examples?
| heavyset_go wrote:
| Check out the docs: https://docs.python.org/3/library/col
| lections.html#collectio...
| d0mine wrote:
| It may be more explicit: OrderedDict has move_to_end() which
| may be useful e.g., for implementing lru_cache-like
| functionality (like deque.rotate but with arbitrary keys).
| masklinn wrote:
| OTOH that's a lot less useful now that functools.lru_cache
| exists: it's more specialised so it's lighter, more
| efficient, and thread-safe. So unless you have extended
| flexibility requirements around your LRU, OD loses a lot
| there.
|
| And if you're using a FIFO cache, threading a regular dict
| through a separate fifo (whether linked list or deque) is
| more efficient in my experience of implementing both S3 and
| Sieve.
| Flimm wrote:
| Two dictionaries with equal keys and values are considered
| equal in Python, even if the order of the entries differ. By
| contrast, two OrderedDict objects are only equal if their
| respective entries are equal and if their order does not
| differ.
| BerislavLopac wrote:
| ChainMap might be the most underrated bit in the standard
| library.
| stevesimmons wrote:
| For anyone wanting some more explanation, ChainMap can be
| used to build nested namespaces from a series of dicts
| without having to explicitly merge the names in each level.
| Updates to the whole ChainMap go into the top-level dict.
|
| The docs are here [0].
|
| Some simple motivating applications:
|
| - Look up names in Python locals before globals before built-
| in functions: `pylookup = ChainMap(locals(), globals(),
| vars(builtins))`
|
| - Get config variables from various sources in priority
| order: `var_map = ChainMap(command_line_args, os.environ,
| defaults)`
|
| - Simulate layered filesystems
|
| - etc
|
| [0] https://docs.python.org/3/library/collections.html#collec
| tio...
| mont_tag wrote:
| My faves are the lru_cache, namedtuples, deques, chainmap, and
| all of the itertools.
| sevensor wrote:
| I mostly migrated to frozen dataclasses from namedtuples when
| dataclasses became available. I'm curious about your preference
| for the namedtuple. Is it the lighter weight, the strong
| immutability, the easy destructing? Or is it that most tuples
| might as well be namedtuples? Those are the advantages I can
| think of anyway :)
| sgarland wrote:
| The main thing I find myself using them for is `_make()`.
| From the canonical [0] example: import
| sqlite3 EmployeeRecord =
| namedtuple('EmployeeRecord', 'name, age, title, department,
| paygrade') conn = sqlite3.connect('/companydata')
| cursor = conn.cursor() cursor.execute('SELECT name,
| age, title, department, paygrade FROM employees') for
| emp in map(EmployeeRecord._make, cursor.fetchall()):
| print(emp.name, emp.title)
|
| You could of course accomplish the same with a dictionary
| comprehension, but I find this to be less noisy. Also, they
| have `_asdict()` should you want to have the contents as a
| dict.
|
| [0]: https://docs.python.org/3/library/collections.html#colle
| ctio...
| judicious wrote:
| Dictionary comprehensions can be very elegant. List and
| dictionary comprehensions are very powerful and expressive
| abstractions. In fact, while not good practice you can
| pretty much write all Python code inside comprehensions
| including stuff regarding mutation.
|
| This is valid(as in it will run, but highly unidiomatic)
| code:
|
| quicksort = lambda arr: [pivot:=arr[0], left:= [x for x in
| arr[1:] if x < pivot], right := [x for x in arr[1:] if x >=
| pivot], quicksort(left) + [pivot] + quicksort(right)][-1]
| if len(arr) > 1 else arr
|
| print(quicksort([1, 33, -4, -2, 110, 5, 88]))
| hansvm wrote:
| Sometimes mutations in comprehensions are very
| expressive. def scan(items, f, initial):
| x = initial return (x := f(x, y) for y in items)
|
| There are lots of other short ways to write `scan`, but I
| don't think any of them map so clearly to a naive
| definition of what it's supposed to do.
| judicious wrote:
| That's incredibly clever, generators are underrated. I
| once challenged my friend to do leetcode problems with
| only expressions. Here's levenshtein distance, however
| it's incredibly clunky.
| levenshtein_distance = lambda s1, s2: [matrix := [[0] *
| (len(s2) + 1) for _ in range(len(s1) + 1)], [
| [ (matrix[i].__setitem__(j,
| min(matrix[i-1][j] + 1, matrix[i][j-1] + 1,
| matrix[i-1][j-1] + (0 if s1[i-1] == s2[j-1] else 1))),
| matrix[i][-1])[1] for j in range(1,
| len(s2) + 1) ] for i in
| range(1, len(s1) + 1) ], matrix[-1][-1]][-1]
| gcr wrote:
| Holy shit that's really clever. Didn't know about _make,
| thank you!
| wodenokoto wrote:
| I'm not quite sure how the fetchall() return type looks,
| but couldn't you just for name, age,
| title in cursor.fetchall(): print(name, age,
| title)
|
| Ofcourse you have to come up with different variable names,
| but it still seems more elegant to just unpack.
| Joker_vD wrote:
| Honestly, the "proper" way should be passing something
| like this def
| namedtuple_factory(cursor, row): fields =
| [column[0] for column in cursor.description]
| cls = namedtuple("Row", fields) return
| cls._make(row)
|
| to the fetchall(), to automatically keep the names in
| sync with those in the SQL query string.
| kstrauser wrote:
| You don't need `_make()` with dataclasses, and you get
| `asdict()` as a stand-alone function so it doesn't clash
| with each class's namespace. Here's what your code might
| look like with them: import sqlite3
| from dataclasses import asdict, dataclass
| @dataclass class EmployeeRecord: name:
| str age: int title: str
| department: str paygrade: str
| conn = sqlite3.connect("/companydata") cursor =
| conn.cursor() cursor.execute("SELECT name, age,
| title, department, paygrade FROM employees") for
| emp in (EmployeeRecord(*row) for row in cursor.fetchall()):
| print(emp.name, emp.title) print(asdict(emp))
| est wrote:
| If I find my self write a[0] a[1] a[2] in more than one
| place, I would upgrade it to a namedtuple. Much better
| readability, can be defined inline like `MyTuple =
| namedtuple('MyTuple', 'k1 k2 k3')`
| gcr wrote:
| Any reason not to consider pydantic as the next step?
| JimDabell wrote:
| Every time I've used Pydantic I've found it to be a tonne
| of friction. The developer ergonomics just don't seem
| right.
|
| These days I use attrs and cattrs, and I'm much happier.
| Everything feels a lot more straightforward.
|
| attrs is what Python's dataclasses were based on, but they
| kept on improving it, so attrs just feels like standard
| Python with a little bit extra.
| tpoacher wrote:
| also more_itertools ! even less known than itertools, but
| equally useful.
| matsemann wrote:
| I just wish python had some better ergonomics/syntactic sugar
| working with itertools and friends. Grouping and mapping and
| filtering and stuff quickly become so unwieldy without proper
| lambdas etc, especially as the typing is quite bad so after a
| few steps you're not sure what you even have.
|
| Just as recent as today I went to Kotlin to process something
| semicomplex even though we're a python shop, just because I
| wanted to bash my head in after a few attempts in python. A DS
| could probably solve it minutes with pandas or something, but
| again stringly typed and lots of guesswork.
|
| (It was actually a friendly algorithmic competition at work, I
| won, and even found a bug in the organizer's code that went
| undetected exactly because of this)
| judicious wrote:
| I find converting things from map objects or filter objects
| back to lists to be a bit clunky. Not to mention chaining
| operations makes it even more clunky. Some syntatic sugar
| would go a long way.
| mturmon wrote:
| I use defaultdict a lot - for accumulators when you're not sure
| about what is coming. Here's a simplified example:
| # a[star_name][instrument] = set of (seed, planet index) of
| visited planets a = defaultdict(lambda:
| defaultdict(set)) for row in rows:
| a[row.star][row.inst].add((row.seed, row.planet))
|
| This is a dict-of-dict-of-set that is accumulating from a
| stream of rows, and I don't know what stars and instruments
| will be present.
|
| Another related tool is Counter (https://docs.python.org/3/libr
| ary/collections.html#collectio...)
| joshdavham wrote:
| I did not know about that webbrowser module. This will definitely
| come in handy for sure!
| fuzztester wrote:
| Try: import antigravity
|
| and import braces
|
| separately.
| adm_ wrote:
| Actually it is from __future__ import braces
| fuzztester wrote:
| Oh yeah, thanks.
|
| That also makes it more funny. :)
| joshdavham wrote:
| That's cool! I didn't know about this one.
|
| Also, just to make sure I understand the joke. It's
| basically just saying that they'll never add braces to the
| python syntax, right?
| chuckadams wrote:
| Don't forget import this
| Uptrenda wrote:
| Throwing frozensets out, too. If regular sets aren't obscure
| enough, frozensets might be your thing. It looks like a set, it
| acts like a set, but its... hashable (for indexing) and
| (immutable.) Why use this? For algorithms that rely on
| combinations (not permutations), frozensets can be very useful.
| E.g. NOT this -- (0, 1) (1, 0) (both distinct using tuples) vs
| frozenset([0, 1]) ([1, 0] or [0, 1] have the same identity /
| frozenset.) You can use this for indexing algorithms and things
| like that. Sometimes, sets are very convenient because they
| naturally 'normalise' entries into a fixed order. This can simply
| a lot of code.
| nick238 wrote:
| The following are identical
| fractions.Fraction(numerator=1, denominator=3)
| fractions.Fraction(1) / 3
|
| ChainMap is maybe better described/used as inheritance for dicts,
| where something like settings =
| ChainMap(instance_settings, region_settings, global_settings)
|
| would give you one object to look in.
| openrisk wrote:
| Some modules are essential additions while others are handy so as
| not to have to manage dependencies.
|
| Good example of the latter use case is the statistics module.
|
| There is a price to pay though: its performance is 10x slower
| than numpy. So its mostly useful when the required calculation is
| not a bottleneck.
|
| The benefit is you are good to go (batteries included) without
| any virtual environmemts, pip's etc.
| dairiki wrote:
| I just discovered graphlib.TopologicalSorter the other day.
|
| Nice! When you need it, you need it. It's nice not to have to
| implement it oneself.
| crabbone wrote:
| Once I found myself needing to sort something topologically...
| and the interface to this sorter is so bad that you cannot
| really retrofit any kind of graph data to make it work with the
| sorter. So, it's kinda worthless, unless you specifically
| design your graph to be sorted with this sorter.
|
| Also, topological sort is like five lines of code... so, it
| doesn't matter if the function is there.
| h4l wrote:
| MappingProxyType is another handy one. It wraps a regular
| dict/Mapping to create a read-only live view of the underlying
| dict. You can use it to expose a dict that can't be modified, but
| doesn't need copying.
|
| https://docs.python.org/3/library/types.html#types.MappingPr...
| teddyh wrote:
| > _file_url = 'file://' + os.path.realpath('test.html')_
|
| You have to encode the file name! file_url =
| 'file://' + urllib.parse.quote(os.path.realpath('test.html'))
| Qem wrote:
| > For people eager to join the AI/ML revolution it provides Naive
| Bayes classifier - an algorithm that can be considered a minimum
| viable example of machine learning.
|
| I don't think this is true. It allows you to specify and
| calculate parameters for normal distributions, what allows you to
| jury rig a naive bayes classifier, what is shown as a doc
| example. This is not the same as providing a built in classifier.
| alexpotato wrote:
| For a funny and insightful tour of the Python "built in"
| functions, I highly recommend Dave Beazley's talk:
|
| https://www.youtube.com/watch?v=j6VSAsKAj98
| skinner927 wrote:
| contextlib.ExitStack is a lesser known trick for limiting context
| manager nesting.
| chadash wrote:
| _> OrderedDict - dictionary that maintains order of key-value
| pairs (e.g. when HTTP header value matters for dealing with
| certain security mechanisms)._
|
| Word to the wise... as of Python 3.7, the regular dictionary data
| structure guarantees order. Declaring an OrderedDict can still be
| worthwhile for readability (to let code reviewers/maintainers
| know that order is important) but I don't know of any other
| reason to use it anymore.
| LudwigNagasena wrote:
| Comparison of OrderedDict is order-sensitive. They also have
| some extra methods.
| buildbot wrote:
| Yep, those extra methods are extremely useful. Basically
| turns them into stack/queues in addition to being
| dictionaries which can be very helpful.
| dataflow wrote:
| > Word to the wise... as of Python 3.7, the regular dictionary
| data structure guarantees order.
|
| Which means you still should use it if you might run on 3.6 or
| earlier.
| sestep wrote:
| Even for 3.6 it's still true, just not guaranteed in writing:
| https://stackoverflow.com/a/39980744/5044950
|
| And Python <=3.7 is already end-of-life anyways:
| https://devguide.python.org/versions/
| Helmut10001 wrote:
| This hit me bad once bad. I tested the regular dict and it
| _looked_ like it was ordered. Turned out, 1 out of about
| 100000 times it was not. And I had a lot of trouble
| identifying the reason 3 weeks later, when the bug was
| buried deep in complex code, and it appeared mostly what
| looked like random.
| willcipriano wrote:
| Being as specific as possible with your types is how you make
| things more readable in Python. OrderedDict where the order
| matters, set where there are no duplicate items possible, The
| newish enums are great for things that have a limited set of
| values (dev, test, qa, prod) vs using a string. You can say a
| lot with type choice.
|
| Another reason is I think that 3.7 behavior is just a C Python
| implementation detail, other interpreters may not honor it.
| sestep wrote:
| You're thinking of 3.6:
| https://stackoverflow.com/a/39980744/5044950
| WhyNotHugo wrote:
| Does dict now guarantee that it maintains order? IIRC, it was
| originally a mere side effect of the algorithm chosen (which
| was chosen for performance), but it could change in future
| releases or alternative implementations.
| metalliqaz wrote:
| afaik the documentation states that it could change in the
| future
| nilslindemann wrote:
| Nope, "Dict keeps insertion order" is the ruling.
|
| https://mail.python.org/pipermail/python-
| dev/2017-December/1...
| eurleif wrote:
| >Changed in version 3.7: Dictionary order is guaranteed to be
| insertion order. This behavior was an implementation detail
| of CPython from 3.6.
|
| https://docs.python.org/3/library/stdtypes.html#dict:~:text=.
| ...
| sgarland wrote:
| Adding `array` [0] to the list. It's generally slower than a
| list, but massively more memory-efficient. You're limited to a
| heterogeneous type, of course, but they can be quite useful for
| some operations.
|
| [0]: https://docs.python.org/3/library/array.html
| cgopalan wrote:
| You mean homogenous instead of heterogenous, right?
| tomjakubowski wrote:
| To add to this, arrays are also restricted to primitive C
| types. A Python array object is simply a heap allocated
| `unsigned long *` or what have you.
|
| https://docs.python.org/3/library/array.html
|
| https://github.com/python/cpython/blob/main/Modules/arraymod.
| ..
|
| And you can use struct for heterogenous data =) It has a neat
| DSL for packing/unpacking the data, reminiscent of the
| "little languages" from classic book The Practice of
| Programming. Python is actually pretty nice working with
| binary data.
|
| https://docs.python.org/3/library/struct.html
| lang4d wrote:
| Why is it slower compared to a normal list?
| timdiggerm wrote:
| The contrast between links and the background colors is too low,
| making this very hard to read.
| tpoacher wrote:
| I was not aware of zipapp ... but it's interesting to see it
| exists as a method for enabling python to run 'zipped packages'
| ... since python can already do that by default with normal
| zipfiles, as long as the zipfile appears / is added to the python
| path (which is roughly analogous to how one can add .jar files to
| the classpath in java). E.g.: export
| PYTHONPATH="package.zip" python3 -m packagename
|
| will work just fine.
|
| (PS. I document this technique in one of my python-template
| projects: https://git.sr.ht/~tpapastylianou/python-self-
| contained-runn...)
|
| I suppose, if the intent is to package something in a manner that
| attempts to make it newbie-proof, then requiring a PYTHONPATH
| incantation before the python part might be one step too far ...
| but then again, one could argue the same about people not quite
| knowing what to do with a .pyz file and getting stuck.
| BiteCode_dev wrote:
| Checkout shiv for turning even more zipapp goodness:
| https://shiv.readthedocs.io/en/latest/
| djoldman wrote:
| TIL decimal and fraction. Pretty cool.
| BiteCode_dev wrote:
| Add functools to the list. Espacially functools.wraps() and
| functools.partial().
|
| The stdlib is full of goodies.
|
| Now I always appreciated the battery included logic in python.
| But I noticed this week that LLM diminish that need. It's so easy
| to prompt for small utilities and saves you from using entire
| libraries for a few tools.
|
| And the AI can create doc and tests for them as quickly.
|
| So while I was really enthusiastic things like pairwise() were
| added to itertools, it's not as revolutionary as before.
| BeetleB wrote:
| And itertools!
| gcr wrote:
| If you're saying that LLMs trade idiomatic tools for ease-of-
| boilerplate-generation, shouldn't that be a point against them,
| not in their favor?
|
| Pardon the hyperbole but it's a bit like lauding an IDE for
| automatically generating thousands of Java class stubs.
| rurp wrote:
| Agreed, rewriting standard functions is much worse than using
| standard tools that already exist.
|
| In addition to the extra boilerplate and reduced readability,
| that also sounds like an easy way to introduce subtle bugs.
| Standard library functions have been exhaustively field
| tested, a similar looking LLM generated function could easily
| include a footgun.
| BiteCode_dev wrote:
| Sure, but have you tried to introduce a new standard tool
| in the stdlib?
|
| It's not a fun process.
|
| Writing the code is the easy part.
|
| And installing more-itertools for one functions is a bit
| silly
| BiteCode_dev wrote:
| For decades you had the famous itertools recipes taunting you
| in the doc: https://docs.python.org/3/library/itertools.html#
| itertools-r...
|
| They were super useful, but not included in the stdlib,
| despite being a few lines long.
|
| We also had more-itertools, bolton, and others, to bridge
| that gap.
|
| Now, there was always a tension between adding more stuff to
| the stdlib, or letting 3rd party libs handle it. Remember the
| saying: the stdlib is where projects go to die.
|
| And of course tensions about installing full on 3rd party
| libs just for a few functions.
|
| The result is that many people copy/pasted a lot of small
| utilities, and endless debates on python-ideas to include
| some more.
|
| I think this is going to slow down. Now if you want "def
| first_true(iterable, default=False, predicate=None)", you ask
| chatgpt, and you don't care.
|
| The cost of adding those into the project is negligeable.
|
| It's nowhere near generating thousand of class stubs. It's
| actually the opposite: very targetted, specific code needs
| being filled instead of haunting python debates or your venv.
|
| But to stimulate a bit your anxiety, I do think code gen is
| going also making a big comeback with LLM :)
| morkalork wrote:
| I wish there were some syntactic sugar for partial but knowing
| how patterns like that get abused in other languages maybe it
| is for the better that there isn't.
| globular-toast wrote:
| What would it look like? Wouldn't it just be lambda?
| BiteCode_dev wrote:
| I wish it would at least be a method on any callable.
| pjot wrote:
| To run a localhost webserver on port 8000, serving the content of
| the current directory: python -m http.server
|
| Pass -h for more options.
| macNchz wrote:
| This is one I use all the time, super handy. Another CLI module
| I regularly make use of is `python -m json.tool`, for
| formatting and validating json.
|
| Last year I ran http.server with -h to remind myself of
| something, and the --cgi flag caught my eye...funnily enough
| there's built in support in the web server for running CGI
| scripts. Alas, it's deprecated and will be removed in 3.13
| later this year, but I when I discovered it I couldn't resist
| the opportunity to write a CGI script for the first time
| 20-something years: https://github.com/drien/python-httpserver-
| upload
| magicmicah85 wrote:
| Probably silly, but I went five years of programming in python
| before I learned about the help function. Only learned about it
| when I had to take an intro to python class for school.
| stavros wrote:
| Well, I went twenty-five years of programming in Python before
| I saw your comment, sooo...
| jjice wrote:
| This is the reason I love python for small personal projects. I
| can get up and going in a heartbeat and the stdlib has so much
| that I'd need. If there was a Flask-style HTTP server and a more
| requests-like HTTP client in the stdlib, I'd be a content man.
| Maybe I need to suck it up, but I just find venvs and Python
| packaging in general annoying to deal with, especially for
| something small.
|
| That said, Go has those things so it's crept in a little bit into
| my quick programming, but I'll always love python.
| guhcampos wrote:
| I've significantly reduced my use of `namedtuple` since
| DataClasses were introduced, but I confess I never did much
| performance comparisons between the two.
|
| I assume the `namedtuple` syntax is more pleasing for Functional
| favorable programmers, but this makes me wonder if the stdlib
| should choose one of them?
| crabbone wrote:
| Last I looked at named tuple implementation, it was along these
| lines:
|
| * generate source code from a template string.
|
| * eval generated code.
|
| * call constructor.
|
| This is woefully slow and wasteful compared to a sensible
| solution: writing it in C. But, nobody really cares.
| twixfel wrote:
| I suspect nobody cares because it's not a problem. That bit
| of code you're moaning about will only be called once per
| namedtuple. It's unlikely to be a problem.
| crabbone wrote:
| Guess who cares? The person you replied to... and it
| would've been really easy to figure that out, given that
| parent went all the way to look for implementation, isn't
| it?
|
| Anyways. The reason I cared is because I was working on a
| Protobuf parser, where named tuple was supposed to play a
| key role: the message class. Imagine my disappointment when
| I started to run benchmarks.
| pletnes wrote:
| In my opinion, namedtuple was created to allow usage of a tuple
| (they are required in many places) while giving names to the
| members, rather than plain indexes.
| rurp wrote:
| I see a lot of mentions of itertools in this thread, which is
| indeed a great library, but I want to mention that
| itertools.groupby is one of the easiest to misuse functions I've
| seen. It's not necessarily intuitive that it groups _contiguous_
| records. Passing it an unsorted list won 't break, but also might
| not return the results you're expecting.
| flakiness wrote:
| Didn't know "dis". It looks nice!
|
| Everyone these days is using ast [1] but the might be room for
| dis instead in some cases.
|
| [1] https://docs.python.org/3/library/ast.html#module-ast
| globular-toast wrote:
| ChainMap is one of my favourites. I like when I find a use for
| it. The obvious one is cascading options type thing (like cmdline
| options -> env -> defaults). I also found a use for it recently
| when changing the underlying storage layer of a class without
| breaking the API.
|
| My other favourite parts of the stdlib are functools and
| itertools. They are both full of stuff that gives you
| superpowers. I always find it a shame when I see developers do an
| ad hoc reimplantation of something in functools/itertools.
| m463 wrote:
| what do people use when they want shorthand for something like
| this: a['foo'] = 20 a['bar'] = 9
|
| where you want to be able to do: a.foo = 20
| a.bar = 9
| hooverd wrote:
| Pydantic, attrs, or dataclasses (standard library option). Or
| you can override __getattr__ on a dict subclass.
___________________________________________________________________
(page generated 2024-09-05 23:01 UTC)