7 ms·
I 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 = namedt
by selectnull 5y ago
I 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'.
- sgtnoodle 5y agoIt's a class factory function, so right off the bat it's a bit weird. The original intent of using spaces was probably to minimize typing. Since they're attribute names they can't have spaces in them, so it's a safe delimiter. You could imagine the function dynamically creates the class by manipulating the underlying dictionary (or whatever the "slot" alternative uses). At that level of python, attributes are strings anyway. Handling spaces is just a matter of calling .split(). In modern python, there's a whole metaclass system that would possibly let you do the equivalent without getting your hands dirty with internal data structures.
- Pokepokalypse 5y agoI envy coders who can actually save time by using a space as a delimiter instead of ['x', 'y']. I really have no use for such syntactic sugar.
- denimnerd42 5y agosyntactic sugar actually drives me nuts because it makes code harder to read for non experts
- sgtnoodle 5y agoYeah, I think more time is wasted in confusion and arguing about style than is saved in keyboard strokes. There's definitely a class of persnickety coders out there though. As a technical leader within a growing organization, sometimes the bulk of my time spent in a code review turns into style guide enforcement. It can get old arguing about the subtle merits of someone's preferred but style violating syntax over and over, especially when all I care about is maintaining a standard of consistency.
- framecowbird 5y agoThis kind of thing grates me: one thing I love about Python is that there is usually only one way of doing everything.
- 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.
- goodside 5y agoThis sounds like a nice idea in theory, and makes a lot of sense for polished, publicly visible libraries where convenience trumps simplicity, but the edge cases can lead to confusing failures and bloat otherwise simple code — as you noted, your example code appears to work for arbitrary objects but actually fails for `str` or `bytes`. A great case study in the issues here is Pandas, which routinely allows arguments to be columns, lists of columns, string column labels, lists of string column labels, and so on. It works surprisingly well, but at the cost of inventing a new semantic distinction between `list` objects and other sequence types like `tuple` — someone unfamiliar with Pandas who thinks “Why does this need to be a list comprehension when a generator expression will do?” is likely introducing a bug. Another subtle issue is that code permissive with inputs is harder to extend via wrapper code. Suppose you have a function that does some sort of processing for any number of given datetimes, but also accepts integer seconds since 1970-01-01, a formatted date string, or any mixed sequence of these types. If you need to write a wrapper that first rounds all times to the most recent hour, your task is much easier if the only accepted type is `Iterable[datetime]`.
- goodside 5y agoI’d speculate it’s meant to mimic Perl’s `qw()` operator, which is like `str.split()` in Python. The module was originally written for contexts where you’re processing SQL result sets with fixed schemas, and before Python these tasks were traditionally handled in Perl. Python inherits a lot of these loose traditions. Similarly, some parts of the standard-lib (`sys`, `os`) follow shell- or C-like naming conventions that would seem bizarre to someone who’s never used a shell prompt.
- dragonwriter 5y ago> I always wondered why is that a space separated string, when a list can work as well. Saves a bunch of typing. 5 chars: 'x y' vs 10: ['x', 'y']
- jeffdn 5y agoWith a non-trivial example that uses readable attribute names, a single, long, space-delimited string becomes more a burden than a convenience, I think. Also, the amount of time saved typing is miniscule in comparison to all the rest of the development work that'll happen.
- dragonwriter 5y ago> With a non-trivial example that uses readable attribute names, a single, long, space-delimited string becomes more a burden than a convenience, I think. For a suitable definition of “non-trivial” and “readable” (where the former is “long list of attributes” and the latter is “long attribute names”), I’d agree, but plenty of real, serious namedtuple use is for namedtuples with small numbers of short attribute names, and those are more readable (in the literal sense) this way. OTOH, for the nontrivial, static uses, you probably want to skip right past namedtuple() with a static list of string literals for names to typing.NamedTuple with its dataclass-like syntax, including type hints, since its more readable and also supports typing. > Also, the amount of time saved typing is miniscule in comparison to all the rest of the development work that'll happen. Sure, but if you start passing on providing (or, on the other side, using) conveniences because each is small in isolation, the aggregate cost ends up being high.
- joshuamorton 5y agoAlso keep in mind interactive use. The space-based approach is nicer when working in a repl, even though I probably wouldn't use it.
- jeffdn 5y agoFair points! Yeah, I exclusively use the typing.NamedTuple declaration these days, because it's: - less redundant - easy to add a per-attribute comment if needed - great when encapsulating disparate data to be able to have concrete types listed
- raymondh 5y agoUsing a list or tuple for the fields is generally best: Point = namedtuple('Point', ('x', 'y')) Support for a space and/or comma separated strings was requested by users. It made life easier for them when syncing with other space/comma separated strings. For example, an SQL query, "SELECT name, rank, serial_number FROM Soldiers;" would have a corresponding named tuple where the field names could be cut-and-pasted from the SQL query. Soldier = namedtuple('Soldier', 'name, rank, serial_number')