15 ms·
Namedtuple in a Post-Dataclasses World
- sayhar 5y agoA little unrelated, but this brings up a question I've had for a while. Seems like one day, everyone around me was using dataclasses. I had not even heard of them. It felt like I had missed some memo or newsletter. It felt weird. Here's my question: what should I have been reading / where should I have been "hanging out" online, so that I would have known that dataclasses were a thing? What are your go-tos for news about new language features, libraries that everyone is using, etc? Hacker news is great, but it doesn't quite fill that need for me, it seems.
- icegreentea2 5y agoI follow the language specific sub-reddits, and I read release notes for major releases of languages (so for python that would be 3.X) even if I wasn't going to jump to the version set.
- genericlemon24 5y ago> I read release notes for major releases of languages _This_, so much. If you are a heavy user of a language / library, it's immensely helpful to look at the release notes every once in a while. Even if you don't plan to upgrade now, it gives you an idea of where things are going (and may eventually tip the scales to a "fuck it, it's now worth upgrading" moment). For Python specifically, PEPs are also a good way to keep track of what's happening (even if some of them don't get accepted): https://www.python.org/dev/peps/ https://www.python.org/dev/peps/ ; there's also an RSS feed: view-source:https://www.python.org/dev/peps/peps.rss/ https://www.python.org/dev/peps/peps.rss/
- emddudley 5y agoPython-centric forums, like r/Python: https://www.reddit.com/r/Python/ https://www.reddit.com/r/Python/ I think the RealPython site is excellent for learning, even for mid to advanced users: https://realpython.com/ https://realpython.com/ They also have a great podcast: https://realpython.com/podcasts/rpp/ https://realpython.com/podcasts/rpp/ Also just browsing the Python docs and release notes.
- pydry 5y agor/Python is 90% newbies showing off toy projects. It's not great for news.
- lbhdc 5y agoI read the release notes. I often see posts for releases here on HN or on reddit, but often I will check in on the official repos or websites to see whats new. I like to spend a few hours a week reading up on whats happening, or try something new to keep up. Checking out new language features is part of that processes to me.
- bobbylarrybobby 5y agoFor Python, you pretty much just need to be aware of when the new major version is released because the "what's new" pages are pretty good. Here's the one in which data classes were released: https://docs.python.org/3/whatsnew/3.7.html https://docs.python.org/3/whatsnew/3.7.html
- chaos_emergent 5y agoConcretely, I found out about dataclasses by using [pydantic](https://pydantic-docs.helpmanual.io/ https://pydantic-docs.helpmanual.io/) and seeing their drop-in `@dataclass` annotation - it got me curious about the adjacent stdlib class. I was using pydantic because I started using FastAPI to build a REST interface, which has pydantic deeply integrated. Generally, I find out about new features through PEP posts, and I reach those by seeing a keyword that I don't know in random code I read online
- dknight10 5y agoA couple good newsletters are Python Weekly and PyCoder's Weekly. They each put out a mix of news, articles/tutorials, and interesting projects. https://www.pythonweekly.com/ https://www.pythonweekly.com/ https://pycoders.com/ https://pycoders.com/
- genericlemon24 5y agoAlready duplicated in my reply to icegreentea2 below, but release notes for projects you use are a great place to get updates. For Python specifically, PEPs are very helpful too: https://www.python.org/dev/peps/ https://www.python.org/dev/peps/
- dec0dedab0de 5y agoI found out about data classes on hn, before they were in the standard library. I also regularly search for python to see what stories I missed. I also like to keep up to date with the PyCon videos, as well as some of the other python conferences. But, as others have said, the release notes are the main source for whats new, if a bit dry. That said, I never actually use data classes. I normally just use dicts, and occasionally named tuples.
- raymondh 5y agoFWIW, here is a PyCon video to get you up to speed on dataclasses: https://www.youtube.com/watch?v=T-TwcmT6Rcw https://www.youtube.com/watch?v=T-TwcmT6Rcw
- nerdponx 5y agoIn the past, Freenode #python, now Libera #python. Also the Python Discord server.
- PaulHoule 5y agoIn practice the hashtable implementation in Python is so fast, particularly for cases like {"x": 51.2, "y": -74.1 } that you don't gain a lot from namedtuples most of the time. I quit benching namedtuples for applications like that a long time ago.
- johtso 5y agoImmutability is nice though.
- wyldfire 5y agoAlso it's nice for bad references to trigger AttributeError which is almost always a design error, whereas KeyError is not always so. I haven't tried it but type hints are probably smart enough to find errors like this statically with namedtuple, but probably not so with a dict.
- gjulianm 5y agoI think you need to use typing.NamedTuple to get typing support. On the other hand, you can use TypedDict [1] to get type hints on dictionaries. 1: https://www.python.org/dev/peps/pep-0589/ https://www.python.org/dev/peps/pep-0589/
- deleted 5y ago[deleted]
- toxik 5y agoa.x is far easier to both read and write than a[”x”] (67% is operator syntax compared to 33% in a.x).
- wcarss 5y agothis and () => {} syntax have always been moderate to strong wins in my book for js when creative-coding
- 5y ago
- sfvisser 5y ago> Point = namedtuple('Point', 'x y') I must come from a different world. What is going on here? Are you dynamically creating a named tuple (a record?) by passing a space separated list of field names? Why?
- cdcarter 5y agoThey are dynamically creating a named tuple class (or prototype). The namedtuple implementation in the python standard library indeed accepts a space separated list of field names. Once it's been defined (as above) then you can create instances (records) like "Point(2,3)"
- selectnull 5y agoI always wondered why is that a space separated string, when a list can work as well. The docs are not well written on that one. This works: Point = namedtuple('Point', ['x', 'y'])
- xav0989 5y agoThe function was defined to either take a space separated list of names or a sequence of names. The docs seem pretty clear to me: > The field_names are a sequence of strings such as ['x', 'y']. Alternatively, field_names can be a single string with each fieldname separated by whitespace and/or commas, for example 'x y' or 'x, y'.
- dec0dedab0de 5y agoI think it comes down to the idea that going out of your way to make the library work either way makes it easier for people to use, even if it makes the library itself a bit more complicated. I wish more library devs would go out of their way to add such niceties. A big one that I always do is if I'm expecting an iterator of objects I make it just work with one. from collections.abc import Iterable def my_function(arg): # slightly different if you're looking for a collection of strings or bytes if not isinstance(arg, Iterable): arg = [arg] for item in arg: do the thing Or if you have a specific type of object you want it goes like this from collections.abc import Iterable def my_function(arg): if isinstance(arg, MyObjectIWant): arg = [arg] for item in arg: do the thing I like to think of my libraries as mini programs for users, and I hate when validation is too strict, when it could be so easy to fix. Like when a phone number validator insists on (XXX)XXX-XXXX or XXX.XXX.XXXX or XXXXXXXXXX when it could just ignore everything that isn't a number and make sure there is 10 of them.
- nikeee 5y agoThere is also a NamedTuple (notice the different casing) from the typing library, which doesn't seem to be mentioned in the article: https://docs.python.org/3/library/typing.html#typing.NamedTuple https://docs.python.org/3/library/typing.html#typing.NamedTu... class Employee(NamedTuple): name: str id: int This is equivalent to: Employee = collections.namedtuple('Employee', ['name', 'id'])
- colejohnson66 5y agoI don’t use Python much, but what’s the difference between a NamedTuple and a regular class?
- akoumis 5y agoNamedTuple is purely a data container. It does not have class functions or a constructor you can use for anything other than setting the data members.
- ZuLuuuuuu 5y agoNamedTuple has the features of a tuple, for example it is immutable. A regular class is mutable.
- palotasb 5y agoNamedTuple or namedtuple instances are tuple instances that have the same properties that regular tuples have. They are immutable (you cannot reassign their fields), you can index into them (a[0], a[1] instead of a.x and a.y), you can unpack them with *a. They can have methods like regular classes can, including additional @property methods. A NamedTuple class cannot inherit from another class, not even other named tuples.
- dec0dedab0de 5y agoa named tuple works exactly like a tuple, except you can also use names to get the items in it. so it is immutable and you can get it via slicing. >>> from collections import namedtuple >>> Hat = namedtuple('Hat', ['style', 'size', 'color']) >>> my_hat = Hat('safari', 'XL', 'Orange') >>> my_hat Hat(style='safari', size='XL', color='Orange') >>> my_hat[0] 'safari' >>> my_hat.color 'Orange' >>> my_hat[1:] ('XL', 'Orange') >>> style, size, color = my_hat >>> size 'XL' >>> If thats all your using your classes for, then a named tuple is probably a better solution, or a dataclass. Though I normally just use dicts in that situation. If I see someone create a class without any methods, or atleast planned methods, I don't let it through code review. EDIT: Also, Raymond Hettinger created named tuples. I'm not normally one for call to authority, or hero worship, but I am a huge fan of his. I recommend that anyone interested in Python should watch as many of his talks as they can. EDIT2: As masklinn pointed out, another really good use of named tuples is when you're already returning a tuple, and you realize it would be better if it had names. You could change it to a named tuple without breaking any of the existing code. Unless they're doing something dumb like halfassing type checking at runtime. (this use case is in the article, which i didn't read at first)
- msravi 5y agoThe syntax is a lot more intuitive in Julia: julia> point = (x=1, y=2) (x = 1, y = 2) julia> point.x 1 julia> point.y 2 julia> dump(point) NamedTuple{(:x, :y), Tuple{Int64, Int64}} x: Int64 1 y: Int64 2
- bobbylarrybobby 5y agoAnd to create one as an anonymous type, you can use the `@NamedTuple` macro: julia> @NamedTuple{x::Int, y::String} NamedTuple{(:x, :y), Tuple{Int64, String}}
- mdcfrancis 5y agothey are also, type stable, strongly typed and have the same overhead as a struct. So an array of NamedTuples takes the minimal space and allocation.
- rdtsc 5y agoI guess one difference is that when you inspect it, it doesn't indicate that it is a `point`, just that it's named tuple of two variables, so it's not exactly equivalent.
- the__alchemist 5y agoDataclasses and Enums have, since their introduction, taken over as my foundation of Python data structures. They've obsoleted NamedTuple, namedtuple, and traditional classes in my code. They're a clean way of defining how difference functions, methods etc should interact with each other.
- synergy20 5y agowhat do you mean by 'traditional classes', dataclasses are more for data-only data structure with no methods?
- the__alchemist 5y agoAs in, classes that aren't tagged as `dataclass` or `Enum`. You can have methods with dataclasses.
- bionhoward 5y agoAlong this line of reasoning I learned to love Pydantic which can make it a breeze to parse and coerce environment variables to the correct types: https://pydantic-docs.helpmanual.io/usage/settings/ https://pydantic-docs.helpmanual.io/usage/settings/ You can make an env.py and override module __getattr__ and then import environment variables just like they're regular Python objects (even booleans, floats, collections, etc, despite .env files being string only Huge force multiplier for ML cuz then you can do hyperparameter optimization just by passing different environment variables in an outer loop (even inside your infrastructure as code) Edit: you can make these classes immutable too: https://pydantic-docs.helpmanual.io/usage/models/#faux-immutability https://pydantic-docs.helpmanual.io/usage/models/#faux-immut...
- jkrubin 5y agoPydantic is an incredible lib. I use it for so many different things on top of misc parsing.
- ElevenPhonons 5y agoYou can also create CLI tools that can load partial or full "presets" defined in JSON. https://github.com/mpkocher/pydantic-cli https://github.com/mpkocher/pydantic-cli
- actually_a_dog 5y agoSpeaking of namedtuple, I would encourage anybody who uses Python and wants to learn a thing or two to read the source code for them. At least one of the things you learn should probably fall in the "what not to do" category. There's a lot going on in there to support all that magic you see from the outside, and it's a little scary in there.
- RhysU 5y agoThis*1000. I have been spending an embarrassing amount of time trying to merge a one-off version of dataclasses with dataclasses to pick up the codegen based on type hints. This stuff is nasty and subtle under the covers. I would rather be dealing with a real closure or with real compositional capabilities. Dataclasses are gross in the weeds. For example, y = dataclass(x) mutates its argument. That is, y = x.
- continuational 5y agoSuch a confusing title without "Python" in there, especially when it's specifically about some Python feature.
- jammycrisp 5y agoY'all may be interested in a fast dataclass-like library I maintain called msgspec (https://jcristharif.com/msgspec/ https://jcristharif.com/msgspec/) that provides many of the benefits of dataclasses (mutable, type declarations), but with speedy performance. The objects are mainly meant to be used for (de)serialization (currently only msgpack is supported, but JSON support is in the works), with native type validation (think a faster pydantic). Mirroring the author's initialization benchmark: In [1]: import msgspec In [2]: from typing import NamedTuple In [3]: class Point(msgspec.Struct): ...: x: int ...: y: int ...: In [4]: class PointNT(NamedTuple): ...: x: int ...: y: int ...: In [5]: %timeit Point(1, 2) 48.4 ns ± 0.195 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each) In [6]: %timeit PointNT(1, 2) 185 ns ± 0.851 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
- nerdponx 5y agoIs this faster than Attrs as well?
- jammycrisp 5y agoYes, but it's also less flexible. Tradeoffs.