
Hi, list ! namedtuples are really great. I would like to use them even more, for example for functions that return multiple arguments. The problem is that namedtuples have to be "declared" beforehand, so it would be quite tedious to declare a nameedtuple by function, that's why I very rarely do it. Another hting I don't like about namedtuples is the duplication of the name. TYpical declarations look like `Point = namedtuple('Point', ['x', 'y'])`, where `Point` is repeated two times. I'll go one step further and say that the name is useless most of the time, so let's just get rid of it. Proposal ======== So I thought about a new (ok, maybe it has been proposed before but I couldn't find it) syntax for anonymous namedtuples (I put the prints as comments, otherwise gmane is complainig about top-posting): my_point = (x=12, y=16) # (x=12, y=16) my_point[0] # 12 my_point.y # 16 type(my_point) # <class 'anonymousnamedtuple'> It's just a tuple, but with names. Parenthesis would be mandatory because `my_point = x = 12, y = 16` wouldn't work. Single elements anonymouns namedtuples would require a trailing comma, similarely to tuples. I'd be happy to make a factory function for my personal use, but the order of kwargs is not respected. To have an elegant syntax, it has to be a construct of the language. The created objects would all be of the same class (with a better name, of course). As it adds no keyword to the language, it would not break compatibility. The created objects could support some namedtuples methods: _asdict, _replace and _fields. The two other methods _make and _source would not apply. Performance-wise, I guess that they would be slower than tuples and namedtuples, But to me the additionnal usability trumps the performance hit. If you have to care about performance, you can still use a namedtuple ot bare tuples. Even further... =============== This initial ideas is useful in itself, but it could be extended even further. I've thought about a possible evolution. The idea is that not all values has to be named: similarely to how args and kwargs work for functions, there could be non-named values, with the same limitations as the arguments (unnamed first, named afterwards). All values could be retrived by indexing, and named values could also be retrieved by their attribute name. This way they could be used in __getitem__ as proposed in PEP 472[0], so that __getitem__ supports additionnal keywords arguments. It would correspond to Strategy "named tuple", with some of the cons removed: "The namedtuple fields, and thus the type, will have to change according to the passed arguments. This can be a performance bottleneck, and makes it impossible to guarantee that two subsequent index accesses get the same Index class;" That would still be true for the performance bottleneck, but since the class would always be the same the second problem disappears. To minimize the performace hit, a standard tuple would be passed to __getitiem__ if there is no keyword argument, and an anonymous namedtuple would be passed if there is a keyword. "the _n "magic" fields are a bit unusual, but ipython already uses them for result history." Those wouldn't be needed if both named and unnamed values are allowed. "Differently from a function, the two notations gridValues[x=3, y=5, z=8] and gridValues[3,5,8] would not gracefully match if the order is modified at call time (e.g. we ask for gridValues[y=5, z=8, x=3]) . In a function, we can pre-define argument names so that keyword arguments are properly matched. Not so in __getitem__ , leaving the task for interpreting and matching to __getitem__ itself." Indexing already doesn't behave like a function call. Keeping the argument order (like this proposal would imply) is a special case of not keeping it, while the reverse is not true, so the more general solution would be implemented. Finally, I admit that I have no idea of how to implement this, I love python but never looked at it's internals. Maybe my proposal is too naive, I really hope not. Thanks for your attention, Joseph [0] https://www.python.org/dev/peps/pep-0472/

On Tue, Apr 19, 2016 at 7:49 PM, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
There have been proposals to have kwargs retain some order (either by having it actually be an OrderedDict, or by changing the native dict type to retain order under fairly restricted circumstances). With that, you could craft the factory function easily. It may be worth dusting off one of those proposals and seeing if it can move forward. That said, though: I don't often feel the yearning for quick namedtuples. A function that today returns a namedtuple of 'x' and 'y' can't in the future grow a 'z' without breaking any callers that unpack "x, y = func()", so extensible return objects have to forego unpacking (eg using a dict or SimpleNamespace). So you still have a sharp division between "tuple" and "thing with arbitrary names", and a namedtuple has to be soundly in the first camp. There *is* a use-case for this, but it's fairly narrow - you have to have enough names that you don't want to just unpack them everywhere, yet still have an order, AND the set of names has to be constant. I suspect the correct solution here is to make it easier for people to write their own namedtuple factories, rather than granting them syntactic support. ChrisA

On 19 April 2016 at 11:06, Chris Angelico <rosuav@gmail.com> wrote:
Possibly the docs for namedtuple should refer the user to SimpleNamespace as an alternative if "being a tuple subclass" isn't an important requirement. Or possibly SimpleNamespace should be in the collections module (alongside namedtuple) rather than in the types module? The issue may simply be that SimpleNamespace isn't as discoverable as it should be? Paul

On Tue, Apr 19, 2016 at 8:25 PM, Paul Moore <p.f.moore@gmail.com> wrote:
That's entirely possible. For the situations where order is insignificant and unpacking is unnecessary, a SimpleNamespace would be perfect, if people knew about it. Probably not worth moving the actual class, but a quick little docs link might help. ChrisA

On 19 April 2016 at 11:46, Chris Angelico <rosuav@gmail.com> wrote:

How big a problem would it be to actually move the class to collections ? For example at the top of the documentation there is a table with all the available container classes, having SimpleNamespace would be far more discoverable than a paragraph in namedtuple. The class could still be importable from types.SimpleNamespace for backward compatibility. Sorry for my noob questions...

On 19 April 2016 at 15:09, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
Not incredibly hard, in theory. However... Move the definition: SimpleNamespace = type(sys.implementation) to collections (but note that this isn't *really* the definition, the actual definition is in C, in the sys module, and is unnamed - to that extent types, which is for exposing names for types that otherwise aren't given built in names, is actually the right place for this definition!) Update the documentation. Update the tests (test/test_types.py) - this probably involves *moving* those tests to test_collections.py. Add a backward compatibility name in types. Add some tests for that backward compatibility name. Work out what to do about pickle compatibility:
Note that the type name (types.SimpleNamespace) is embedded in the pickle. How do we avoid breaking pickles? That's probably far from everything - this was 5 minutes' quick investigation, and I'm not very experienced at doing this type of refactoring. I'm pretty sure I've missed some things.
The class could still be importable from types.SimpleNamespace for backward compatibility.
Where it's defined matters in the pickle case - so it's not quite that simple.
Sorry for my noob questions...
Not at all. It's precisely because it "seems simple" that the feedback people get seems negative at times - I hope the above gives you a better idea of what might be involved in such a seemingly simple change. So thanks for asking, and giving me the opportunity to clarify :-) In summary: It's not likely to be worth the effort, even though it looks simple at first glance. Paul

On 19 April 2016 at 13:34, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
But I still think that my proposal has some value outside of SimpleNamespace. :)
The biggest issue is likely to be that the added value doesn't justify the cost of new syntax, and a language change. On the other hand, functions preserving the order of keyword arguments (which would allow you to write a cleaner factory function) is probably a change with wider value, as well as being less intrusive (it's a semantic change, but there's no change in syntax) and so may be more likely to get through. A lot of the difficulty with assessing proposals like this is balancing the costs and benefits, particularly as the costs typically affect far more people, most of whom don't participate in these lists, so we have to take a cautious ("assume the worst") view. Personally, I've not used namedtuple enough to feel that it warrants dedicated syntax. OTOH, I have wished for something like SimpleNamespace lots of times, so making that more discoverable would have been a huge win for me! Paul

On Tue, Apr 19, 2016 at 01:47:09PM +0100, Paul Moore wrote:
I think there are more problems with the proposal than just "not useful enough". See my previous post.
It's a pretty big semantic change though. As I point out in my previous post, at the moment we can be sure that changing the order of keyword arguments does not change anything: spam(a=1, b=2) and spam(b=2, a=1) will always have the same semantics. Making keyword arguments ordered will break that assumption, and even if it doesn't break any existing code, it will make it harder to reason about future code. No more can you trust that the order of keyword arguments will have no effect on the result of calling a function. I don't see the current behaviour of keyword arguments as a limitation, I see it as a feature. I don't need to care about the order of keyword arguments, only their names. -- Steve

I think I finally understand your concern about keeping the order of keywords arguments. Most of the time it wouldn't matter but it can potentially lead to very surprising behavior. Maybe the fact that we're all consenting adults can help ? However in my proposal there is no function call, even if the syntax is similar. The order of the fields has the same significance as in a namedtuple, but it's another (easier) way to set them. It's also why I proposed an evolution to use it in __getitem__ also, which already doesn't behave like a standard function call either. Joseph

On Tue, Apr 19, 2016 at 10:06:28PM +1000, Steven D'Aprano wrote:
I've thought about this some more, and I've decided that I don't think it should be in collections. It's not a collection. Strangely, "collection" is not in the glossary: https://docs.python.org/dev/glossary.html (neither is "container") and there doesn't appear to be an ABC for what makes a collection, but the docs seem to suggest that "collections" are another word for "containers": Quote: 8.3. collections — Container datatypes Source code: Lib/collections/__init__.py This module implements specialized container datatypes providing alternatives to Python’s general purpose built-in containers, dict, list, set, and tuple. https://docs.python.org/dev/library/collections.html which mostly matches the old (and I mean really old, going back to Python 1.5 days) informal usage of "collection" as "a string, list, tuple or dict", that is, a sequence or mapping. (These days, I'd add set to the list as well.) SimpleNamespace is neither a sequence nor a mapping. We do have a "Container" ABC: https://docs.python.org/dev/library/collections.abc.html#collections.abc.Con... and SimpleNamespace doesn't match that ABC either. So I think SimpleNamespace should stay where it is. I guess I'll just have to learn that it's a type, not a collection :-) -- Steve

SimpleNamespace is neither a sequence nor a mapping.
I don't know the exact definition of a mapping, but to me SimpleNamespace is like a dict with restricted keys (valid attributes only) and a nicer syntax. `my_dict["key"]` is roughly equivalent to `my_namespace.key`. SimpleNamespace lacks lots of methods comapred to dict. Maybe an hypothetical ComplexNamespace would be in collections module ? Joseph

On Tue, Apr 19, 2016 at 08:47:13PM +0000, Joseph Martinot-Lagarde wrote:
That is (I believe) how Javascript and PHP treat it, but they're not exactly the best languages to emulate, or at least not blindly. Attributes and keys represent different concepts. Attributes represent an integral part of the object: dog.tail me.head car.engine book.cover while keys represent arbitrary (or nearly so) data associated with some data collection: books['The Lord Of The Rings'] kings['Henry VIII'] prisoner[239410] colours['AliceBlue'] They don't just use different syntaxes, they have different purposes, and while it is tempting to (mis)use the shorter attribute syntax for key lookups: colours.AliceBlue it is risky to conflate the two. Suppose you have a book called "update" (presumably a book of experimental poetry by somebody who dislikes uppercase letters): books.update Either the key shadows the update method, or the method shadows the book, or you get an error. All of these scenarios are bad. I'd consider giving Python an alternate key-lookup syntax purely as syntactic sugar: colours~AliceBlue # sugar for colours['AliceBlue'] books~update # books['update'] before I would consider adding a standard library class that conflates attribute- and key-lookup. If people want to do this in their own code (and I do see the attraction, even if I think it is a bad idea), so be it, but the standard library shouldn't encourage it. -- Steve

On Wed, Apr 20, 2016 at 12:48 PM, Steven D'Aprano <steve@pearwood.info> wrote:
Enumerations blur the line. You could define 'colours' thus: class colours(enum.IntEnum): AliceBlue = 0xf0f8ff Is "AliceBlue" a fundamental attribute of the "colours" object, or is it a piece of data associated with the collection of colours? Or, like Danny Kaye, perchance a brilliant combination of both? ChrisA

On Tue, Apr 19, 2016, at 06:25, Paul Moore wrote:
Just my two cents - for the use cases that I would find this useful for (I usually end up just using tuple), a hashable "FrozenSimpleNamespace" would be nice. Or even one that has immutable key fields that are used as the basis for the hash but that you can hang other values off of (SemiFrozen?) A way to simply initialize a SimpleNamespace-like class with a passed-in mapping, and have it inherit the equality/hash/etc from that (so FrozenSimpleNamespace could use FrozenDict, you could do one with OrderedDict, one with chainmap or with an easy-to-write custom dict that provides the "immutable key plus mutable other" behavior), might provide for all of these in a relatively easy way. Maybe have SimpleNamespace([dict], /, **kwargs) that just throws the dict argument (if present) into __dict__. If there were a FrozenOrderedDict you could even implement a very namedtuple-like class that way.

On 19 April 2016 at 15:26, Random832 <random832@fastmail.com> wrote:
Having done some digging just now... SimpleNamespace is basically just exposing for end users, the type that is used to build the sys.implementation object. The definition is *literally* nothing more than SimpleNamespace = type(sys.implementation) Variations such as you suggest may indeed be useful, but the existing implementation was essentially a free benefit of "we use this one ourselves in the core". Going beyond that, any additional types probably need to justify themselves a bit better - and at that point the usual "publish on PyPI as a standalone module and see how useful they turn out to be" suggestion probably applies. Paul

On 19 April 2016 at 15:51, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
I was referring to randon832's suggested variants on SimpleNamespace. As you say, your proposal is basically a language change and you're completely right to assume that needs to be implemented in the core. Sorry if I wasn't clear enough. Paul

On Tue, Apr 19, 2016 at 5:39 PM, Paul Moore <p.f.moore@gmail.com> wrote:
So, if this were added to 'collections' too, the documentation should be moved there, and the 'types' documentation could mention this somehow and recommend using collections. Heck, if it gets another alias, why not give it another name too: collections.ComplicatedNamespace ;-) My main objection to putting SimpleNamespace in collections is that we might want something even better in collections, perhaps ComplexNamespace? -Koos

On Tue, Apr 19, 2016 at 8:39 AM, Paul Moore <p.f.moore@gmail.com> wrote:
FYI, sys.implementation was added for PEP 421 (May-ish 2012). That PEP has a small section on the type I used. [1] At first it was unclear if I should even expose type(sys.implementation). [2] Nick suggested types.SimpleNamespace, so I went with that. [3] :) Note that the type is super simple/trivial, a basic subclass of object with a **kwargs __init__() to pre-populate and a nice repr. Both that first link [1] and the docs [4] spell it out. The point is that there isn't much to the type. It's a convenience, nothing else. I used to get roughly the same thing with "class SimpleNamespace: pass". :) FWIW, I proposed giving SimpleNamespace more exposure around the same time as PEP 421, and the reaction was lukewarm. [5] However, since then it's been used in several other places in the stdlib and I know of a few folks that have used it in their own projects. Regardless, ultimately the only reason I added it to the stdlib in the first place [6] was because it's the type of sys.implementation and it made more sense to expose it explicitly in the types module than implicitly via type(sys.implementation). -eric [1] https://www.python.org/dev/peps/pep-0421/#type-considerations [2] https://mail.python.org/pipermail/python-dev/2012-May/119771.html [3] https://mail.python.org/pipermail/python-dev/2012-May/119775.html [4] https://docs.python.org/3/library/types.html#types.SimpleNamespace [5] https://mail.python.org/pipermail/python-ideas/2012-May/015208.html [6] in contrast to argparse.Namespace and multiprocessing.managers.Namespace...

Chris Angelico <rosuav@...> writes:
I saw some proposals but forgot about them, thanks for the reminder. I'd prefer my proposal for two reasons: - the syntax is nicer that a factory function - it wouldn't be possible to add keyword arguments to __getitem__ without breaking compatibility Those issues are relatively minor, i'd be happy with a factory function
For all my use cases (not only function returns) I would completely replace namedtuple by anonymouns namedtuple.

On Tue, Apr 19, 2016 at 9:31 PM, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
Agreed, the syntax is a lot nicer - for this specific situation. Don't forget, though, that every piece of new syntax carries with it the not insignificant cost of complexity; and some things are better represented by function calls than syntax (cf 'print'). With "from types import SimpleNamespace as NS" at the top of your code, you can use the keyword-arguments form of the constructor to be almost the same as your proposal, without any new syntax. When a subsequent maintainer looks at your code, s/he can quickly look up at the imports to see what's going on, instead of having to learn another piece of syntax.
I have to agree. Fortunately it isn't hard to create a namedtuple factory: def NS(fields): return namedtuple('anonymous', fields.split()) or possibly: def NS(fields, *values): return namedtuple('anonymous', fields.split())(*values) That cuts down the duplication some, but it's far from perfect. ChrisA

Chris Angelico <rosuav@...> writes:
order
I agree on the principle, but to me this syntax looks less complex to me compared to the actual namedtuple where you have to use a factory to create a class to be able to use a namedtuple. And if you use a namedtuple as a return value, the definition of the namedtuple class will typically be relatively far away from the actual use of it. SimpleNamespace is nice but would break compatibility for return values.
It cuts down the duplication at the cost of readability. There is also the Matlab way which looks a bit better: from collections import namedtuple def NS(*args): fields = args[::2] values = args[1::2] return namedtuple('anonymous', fields)(*values) print(NS("x", 12, "y", 15)) But readability counts, and it's very easy to introduce bugs as adding or removing arguments can impact the whole chain. Initially coming from Matlab, the greatest interest I found in python was named arguments for functions! :)

On Tue, Apr 19, 2016 at 4:49 AM, Chris Angelico <rosuav@gmail.com> wrote:
Please don't recommend or spread this idiom! Every call to namedtuple() creates a new class, which is a very expensive operation. On my machine the simplest namedtuple call taks around 350 usec. -- --Guido van Rossum (python.org/~guido)

A general warning about this (x=12, y=16) idea: It's not so different from using dicts as cheap structs, constructing objects on the fly using either {'x': 12, 'y': 16} or dict(x=12, y=16). The problem with all these this is that if you use this idiom a lot, you're invariably going to run into cases where a field is missing, and you're spending a lot of time tracking down where the object was created incorrectly. Using a namedtuple (or any other construct that asks you to pre-declare the type used) the incorrect construction will cause a failure right at the point where it's being incorrectly constructed, making it much simpler to diagnose. In fully typed languages like Haskell or Java this wouldn't be a problem, but in languages like Python or Perl it is a real concern. -- --Guido van Rossum (python.org/~guido)

Guido van Rossum wrote:
If there were support from the compiler for a function def f(): return x=1, y=2 the namedtuple("_", "x y") class could be stored in f.__code__.co_consts just like 1 and 2. Adding information about the file and line number could probably be handled like it's done for code objects of classes and functions defined inside a function. While this approach still produces "late" failures debugging should at least be easier than for dict or SimpleNamespace instances.

Guido van Rossum <guido@...> writes: that if you use this idiom a lot, you're invariably going to run into cases where a field is missing, and you're spending a lot of time tracking down where the object was created incorrectly. Using a namedtuple (or any other construct that asks you to pre-declare the type used) the incorrect construction will cause a failure right at the point where it's being incorrectly constructed, making it much simpler to diagnose. I think that it depends a lot on what these are used for. What I primarily though about was to be able to easily return a namadtuple as a function output. In this case the namedtuple (anonymous or not) is created in a single place, so having to declare the namedtuple before using it has a limited interest, and has the drawbacks I presented before (code duplication, declaration far away from the use). What you're talking about is more like a container which would be used all around an application, where you need to ensure the corecntess of the struct everywhere. In this case a standard nametuple is a better fit. I feel like it's similar to the separation you talked about before, script vs application. My view is more script-like, yours is more application-like. Joseph

On Tue, Apr 19, 2016 at 12:06 PM, Guido van Rossum <guido@python.org> wrote:
Every call to namedtuple() creates a new class, which is a very expensive operation. On my machine the simplest namedtuple call taks around 350 usec.
Isn't that because the code for namedtuple is using exec instead a more pythonic approach of metaclassing to make it "faster" but taking longer to actually create the class? http://bugs.python.org/issue3974 Maybe instead of changing namedtuple (which seems to be a taboo), there could be a new anonymous type. Something built-in, with its own syntax

On Tue, Apr 19, 2016 at 9:58 AM, João Bernardo <jbvsmo@gmail.com> wrote:
That's part of it, but no matter how you do it, it's still creating a new class object, you can't get around that. And class objects are just expensive. Any idiom that ends up creating a new class object for each instance that's created is a big anti-pattern.
Maybe instead of changing namedtuple (which seems to be a taboo), there could be a new anonymous type. Something built-in, with its own syntax.
That's essentially what the (x=12, y=16) proposal is about, IIUC -- it would just be a single new type, so (x=12, y=16).__class__ would be the same class object as (a='', b=3.14). But I have serious reservations about that idiom too. -- --Guido van Rossum (python.org/~guido)

On 19.04.2016 19:35, Guido van Rossum wrote:
The proposal reminds me of JavaScript's "object". So, "(x=12, y=16).__class__ == type(object())"?
But I have serious reservations about that idiom too.
Me, too. I don't fully support this kind of on-the-fly construction as it is the same for closures. But that might just be my personal feeling because as such they escape proper testing and type support by IDEs (which reminds me strongly about Web development with JavaScript). On the other side, it allows ultra-rapid prototyping from which one can strip down to "traditional development" step by step when needed (using classes, tests etc.). This said, what are the reasons for your reservations? Best, Sven

On Tue, Apr 19, 2016 at 4:06 AM, Chris Angelico <rosuav@gmail.com> wrote:
FYI, PEP 468: "Preserving the order of **kwargs in a function." [1] The PEP exists for exactly the sort of use case being discussed here. In my case it was an alternate enum proposal I was making back when enums were under discussion. Regardless, I'd still like to see the PEP land. It's just a matter of finding time. I'll see if I can get some consensus leading up to and at PyCon next month. The actual implementation for PEP 468 is almost trivial. Now that we have a C-implementation of OrderedDict, it's mostly just a matter of addressing performance concerns [2], particularly those expressed by Guido, or falling back to one of the alternatives discussed in the PEP. Note that a related concept is represented with my work to make the class definition namespace ordered by default. [3] It would allow class decorators to have access to the order in which the class's attributes were defined. -eric [1] https://www.python.org/dev/peps/pep-0468/ [2] https://www.python.org/dev/peps/pep-0468/#performance [3] http://bugs.python.org/issue24254

This way they could be used in __getitem__ as proposed in PEP 472[0]
One of the link in this PEP is https://mail.python.org/pipermail/python-ideas/2013-June/021257.html where the writer raises some concerns about named tuples: - They pose problems with pickle because namedtuples needs subclasses to work. In my proposal it shouldn't be a problem anymore since there would be one class. - namedtuple() is a factory function requiring a 2-step initialization, a name, and a subclass. Again it disappears in my proposal. I'm not sure about the database problem since I don't use them.

On Tue, Apr 19, 2016 at 09:49:44AM +0000, Joseph Martinot-Lagarde wrote:
You aren't forced to declare the type ahead of time, you can just use it as part of an expression: py> from collections import namedtuple py> my_tuple = namedtuple("_", "x y z")(1, 2, 3) py> print(my_tuple) _(x=1, y=2, z=3) However, there is a gotcha if you do this: each time you create an anonymous namedtuple, you create a new, distinct, class: py> a = namedtuple("_", "x y")(1, 2) py> b = namedtuple("_", "x y")(1, 2) py> type(a) == type(b) False which could be both surprising and expensive. One possible solution: keep your own cache of classes: def nt(name, fields, _cache={}): cls = _cache.get((name, fields), None) if cls is None: cls = _cache[(name, fields)] = namedtuple(name, fields) return cls
The name is not useless. It is very useful for string representations, debugging, introspection, and generally having a clue what the object represents. How else do you know what kind of object you are dealing with? I agree that it is a little sad that we have to repeat the name twice, but strictly speaking, you don't even need to do that. For example: class Point(namedtuple("AbstractPoint", "x y z")): def method(self): ... In my opinion, avoiding having to repeat the name twice is a "nice to have", not a "must have".
How do you know that the 0th item is field "x"? Keyword arguments are not ordered. Even if you could somehow determine the order that they are given, you can't use that information since we should expect that: assert (x=12, y=16) == (y=16, x=12) will pass. (Why? Because they're keyword arguments, and the order of keyword arguments shouldn't matter.) So we have a problem that the indexing order (the same order is used for iteration and tuple unpacking) is not specified anywhere. This is a *major* problem for an ordered type like tuple. namedtuple avoids this problem by requiring the user to specify the field name order before creating an instance. SimpleNamespace avoids this problem by not being ordered or iterable. I suppose we could put the fields in sorted order. But that's going to make life difficult for uses where we would like some other order, e.g. to match common conventions. Consider a 3D point in spherical coordinates: pt = (r=3, theta=0.5, phi=0.25) In sorted order, pt == (3, 0.25, 0.5) which goes against the standard mathematical definition. Namedtuples pre-define what fields are allowed, what they are called, and what order they appear in. Anonymous namedtuples as you describe them don't do any of these things. Consider that since they're tuples, we should be able to provide the items as positional arguments to the construct, just like regular namedtuples: pt = (x=12, y=16) type(pt)(1, 2) This works fine with namedtuple, but how will it work with your proposal? And what happens if we do this? type(pt)(1, 2, 3) And of course, a naive implementation would suffer from the same issue as mentioned above, where every instance is a singleton of a distinct class. Python isn't a language where we care too much about memory use, but surely we don't want to be quite this profligate: py> a = namedtuple("Point", "x y z")(1, 2, 3) py> sys.getsizeof(a) # reasonably small 36 py> sys.getsizeof(type(a)) # not so small 420 Obviously we don't want every instance to belong to a distinct class, so we need some sort of cache. SimpleNamespace solves this problem by making all instances belong to the same class. That's another difference between namedtuple and what you seem to want. -- Steve

Steven D'Aprano <steve@...> writes:
This looks nice with a short number of short attribute names, but in a real case separating the values from their corresponding field hurts readability. Compare: my_tuple = namedtuple("_", "site, gisement, range_nominal, range_bista, is_monostatic")(12.45, 45.0, 3000.0, 2998.5357, True) my_tuple = (site=12.45, gisement=45.0, range_nominal=3000.0, range_bista=2998.5357, is_monostatic=True) As a side note, if the empty string would be allowed for the class name the printed value would look better. The fact that it's not possible right now looks liek an implementation "detail".
Of course he name is not completely useless, but you can often know what a namedtuple represents in your application or your script from the field names only (or the variable name). SimpleNamespace live very well without a name, for example.
In my proposal these are not keywords arguments, they are a syntax construct to build a anonymous namedtuple. That's why I can't just create a factory function. The order is determiend by the construction, and can be found by introspection (simply printing the object will do). I suppose that as a developper it's a shift from how keywords behave now, but as a user a namedtuple is still a tuple, and it keeps the ordering.
They inherits tuples, that doesn't mean that they behave in all cases like tuples. In that case I guess that this form would not be allowed. I don't know how bad this looks for a python dev though!
Yes, that's another difference, I don't want to replicate namedtuples exactly (otherwise I'd just use a namedtuple). I don't think that you need a cache, more like a frozendict per instance which binds the fields to the corresponding index. Maybe it's what you call cache ?

On Tue, Apr 19, 2016 at 7:49 PM, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
There have been proposals to have kwargs retain some order (either by having it actually be an OrderedDict, or by changing the native dict type to retain order under fairly restricted circumstances). With that, you could craft the factory function easily. It may be worth dusting off one of those proposals and seeing if it can move forward. That said, though: I don't often feel the yearning for quick namedtuples. A function that today returns a namedtuple of 'x' and 'y' can't in the future grow a 'z' without breaking any callers that unpack "x, y = func()", so extensible return objects have to forego unpacking (eg using a dict or SimpleNamespace). So you still have a sharp division between "tuple" and "thing with arbitrary names", and a namedtuple has to be soundly in the first camp. There *is* a use-case for this, but it's fairly narrow - you have to have enough names that you don't want to just unpack them everywhere, yet still have an order, AND the set of names has to be constant. I suspect the correct solution here is to make it easier for people to write their own namedtuple factories, rather than granting them syntactic support. ChrisA

On 19 April 2016 at 11:06, Chris Angelico <rosuav@gmail.com> wrote:
Possibly the docs for namedtuple should refer the user to SimpleNamespace as an alternative if "being a tuple subclass" isn't an important requirement. Or possibly SimpleNamespace should be in the collections module (alongside namedtuple) rather than in the types module? The issue may simply be that SimpleNamespace isn't as discoverable as it should be? Paul

On Tue, Apr 19, 2016 at 8:25 PM, Paul Moore <p.f.moore@gmail.com> wrote:
That's entirely possible. For the situations where order is insignificant and unpacking is unnecessary, a SimpleNamespace would be perfect, if people knew about it. Probably not worth moving the actual class, but a quick little docs link might help. ChrisA

On 19 April 2016 at 11:46, Chris Angelico <rosuav@gmail.com> wrote:

How big a problem would it be to actually move the class to collections ? For example at the top of the documentation there is a table with all the available container classes, having SimpleNamespace would be far more discoverable than a paragraph in namedtuple. The class could still be importable from types.SimpleNamespace for backward compatibility. Sorry for my noob questions...

On 19 April 2016 at 15:09, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
Not incredibly hard, in theory. However... Move the definition: SimpleNamespace = type(sys.implementation) to collections (but note that this isn't *really* the definition, the actual definition is in C, in the sys module, and is unnamed - to that extent types, which is for exposing names for types that otherwise aren't given built in names, is actually the right place for this definition!) Update the documentation. Update the tests (test/test_types.py) - this probably involves *moving* those tests to test_collections.py. Add a backward compatibility name in types. Add some tests for that backward compatibility name. Work out what to do about pickle compatibility:
Note that the type name (types.SimpleNamespace) is embedded in the pickle. How do we avoid breaking pickles? That's probably far from everything - this was 5 minutes' quick investigation, and I'm not very experienced at doing this type of refactoring. I'm pretty sure I've missed some things.
The class could still be importable from types.SimpleNamespace for backward compatibility.
Where it's defined matters in the pickle case - so it's not quite that simple.
Sorry for my noob questions...
Not at all. It's precisely because it "seems simple" that the feedback people get seems negative at times - I hope the above gives you a better idea of what might be involved in such a seemingly simple change. So thanks for asking, and giving me the opportunity to clarify :-) In summary: It's not likely to be worth the effort, even though it looks simple at first glance. Paul

On 19 April 2016 at 13:34, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
But I still think that my proposal has some value outside of SimpleNamespace. :)
The biggest issue is likely to be that the added value doesn't justify the cost of new syntax, and a language change. On the other hand, functions preserving the order of keyword arguments (which would allow you to write a cleaner factory function) is probably a change with wider value, as well as being less intrusive (it's a semantic change, but there's no change in syntax) and so may be more likely to get through. A lot of the difficulty with assessing proposals like this is balancing the costs and benefits, particularly as the costs typically affect far more people, most of whom don't participate in these lists, so we have to take a cautious ("assume the worst") view. Personally, I've not used namedtuple enough to feel that it warrants dedicated syntax. OTOH, I have wished for something like SimpleNamespace lots of times, so making that more discoverable would have been a huge win for me! Paul

On Tue, Apr 19, 2016 at 01:47:09PM +0100, Paul Moore wrote:
I think there are more problems with the proposal than just "not useful enough". See my previous post.
It's a pretty big semantic change though. As I point out in my previous post, at the moment we can be sure that changing the order of keyword arguments does not change anything: spam(a=1, b=2) and spam(b=2, a=1) will always have the same semantics. Making keyword arguments ordered will break that assumption, and even if it doesn't break any existing code, it will make it harder to reason about future code. No more can you trust that the order of keyword arguments will have no effect on the result of calling a function. I don't see the current behaviour of keyword arguments as a limitation, I see it as a feature. I don't need to care about the order of keyword arguments, only their names. -- Steve

I think I finally understand your concern about keeping the order of keywords arguments. Most of the time it wouldn't matter but it can potentially lead to very surprising behavior. Maybe the fact that we're all consenting adults can help ? However in my proposal there is no function call, even if the syntax is similar. The order of the fields has the same significance as in a namedtuple, but it's another (easier) way to set them. It's also why I proposed an evolution to use it in __getitem__ also, which already doesn't behave like a standard function call either. Joseph

On Tue, Apr 19, 2016 at 10:06:28PM +1000, Steven D'Aprano wrote:
I've thought about this some more, and I've decided that I don't think it should be in collections. It's not a collection. Strangely, "collection" is not in the glossary: https://docs.python.org/dev/glossary.html (neither is "container") and there doesn't appear to be an ABC for what makes a collection, but the docs seem to suggest that "collections" are another word for "containers": Quote: 8.3. collections — Container datatypes Source code: Lib/collections/__init__.py This module implements specialized container datatypes providing alternatives to Python’s general purpose built-in containers, dict, list, set, and tuple. https://docs.python.org/dev/library/collections.html which mostly matches the old (and I mean really old, going back to Python 1.5 days) informal usage of "collection" as "a string, list, tuple or dict", that is, a sequence or mapping. (These days, I'd add set to the list as well.) SimpleNamespace is neither a sequence nor a mapping. We do have a "Container" ABC: https://docs.python.org/dev/library/collections.abc.html#collections.abc.Con... and SimpleNamespace doesn't match that ABC either. So I think SimpleNamespace should stay where it is. I guess I'll just have to learn that it's a type, not a collection :-) -- Steve

SimpleNamespace is neither a sequence nor a mapping.
I don't know the exact definition of a mapping, but to me SimpleNamespace is like a dict with restricted keys (valid attributes only) and a nicer syntax. `my_dict["key"]` is roughly equivalent to `my_namespace.key`. SimpleNamespace lacks lots of methods comapred to dict. Maybe an hypothetical ComplexNamespace would be in collections module ? Joseph

On Tue, Apr 19, 2016 at 08:47:13PM +0000, Joseph Martinot-Lagarde wrote:
That is (I believe) how Javascript and PHP treat it, but they're not exactly the best languages to emulate, or at least not blindly. Attributes and keys represent different concepts. Attributes represent an integral part of the object: dog.tail me.head car.engine book.cover while keys represent arbitrary (or nearly so) data associated with some data collection: books['The Lord Of The Rings'] kings['Henry VIII'] prisoner[239410] colours['AliceBlue'] They don't just use different syntaxes, they have different purposes, and while it is tempting to (mis)use the shorter attribute syntax for key lookups: colours.AliceBlue it is risky to conflate the two. Suppose you have a book called "update" (presumably a book of experimental poetry by somebody who dislikes uppercase letters): books.update Either the key shadows the update method, or the method shadows the book, or you get an error. All of these scenarios are bad. I'd consider giving Python an alternate key-lookup syntax purely as syntactic sugar: colours~AliceBlue # sugar for colours['AliceBlue'] books~update # books['update'] before I would consider adding a standard library class that conflates attribute- and key-lookup. If people want to do this in their own code (and I do see the attraction, even if I think it is a bad idea), so be it, but the standard library shouldn't encourage it. -- Steve

On Wed, Apr 20, 2016 at 12:48 PM, Steven D'Aprano <steve@pearwood.info> wrote:
Enumerations blur the line. You could define 'colours' thus: class colours(enum.IntEnum): AliceBlue = 0xf0f8ff Is "AliceBlue" a fundamental attribute of the "colours" object, or is it a piece of data associated with the collection of colours? Or, like Danny Kaye, perchance a brilliant combination of both? ChrisA

On Tue, Apr 19, 2016, at 06:25, Paul Moore wrote:
Just my two cents - for the use cases that I would find this useful for (I usually end up just using tuple), a hashable "FrozenSimpleNamespace" would be nice. Or even one that has immutable key fields that are used as the basis for the hash but that you can hang other values off of (SemiFrozen?) A way to simply initialize a SimpleNamespace-like class with a passed-in mapping, and have it inherit the equality/hash/etc from that (so FrozenSimpleNamespace could use FrozenDict, you could do one with OrderedDict, one with chainmap or with an easy-to-write custom dict that provides the "immutable key plus mutable other" behavior), might provide for all of these in a relatively easy way. Maybe have SimpleNamespace([dict], /, **kwargs) that just throws the dict argument (if present) into __dict__. If there were a FrozenOrderedDict you could even implement a very namedtuple-like class that way.

On 19 April 2016 at 15:26, Random832 <random832@fastmail.com> wrote:
Having done some digging just now... SimpleNamespace is basically just exposing for end users, the type that is used to build the sys.implementation object. The definition is *literally* nothing more than SimpleNamespace = type(sys.implementation) Variations such as you suggest may indeed be useful, but the existing implementation was essentially a free benefit of "we use this one ourselves in the core". Going beyond that, any additional types probably need to justify themselves a bit better - and at that point the usual "publish on PyPI as a standalone module and see how useful they turn out to be" suggestion probably applies. Paul

On 19 April 2016 at 15:51, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
I was referring to randon832's suggested variants on SimpleNamespace. As you say, your proposal is basically a language change and you're completely right to assume that needs to be implemented in the core. Sorry if I wasn't clear enough. Paul

On Tue, Apr 19, 2016 at 5:39 PM, Paul Moore <p.f.moore@gmail.com> wrote:
So, if this were added to 'collections' too, the documentation should be moved there, and the 'types' documentation could mention this somehow and recommend using collections. Heck, if it gets another alias, why not give it another name too: collections.ComplicatedNamespace ;-) My main objection to putting SimpleNamespace in collections is that we might want something even better in collections, perhaps ComplexNamespace? -Koos

On Tue, Apr 19, 2016 at 8:39 AM, Paul Moore <p.f.moore@gmail.com> wrote:
FYI, sys.implementation was added for PEP 421 (May-ish 2012). That PEP has a small section on the type I used. [1] At first it was unclear if I should even expose type(sys.implementation). [2] Nick suggested types.SimpleNamespace, so I went with that. [3] :) Note that the type is super simple/trivial, a basic subclass of object with a **kwargs __init__() to pre-populate and a nice repr. Both that first link [1] and the docs [4] spell it out. The point is that there isn't much to the type. It's a convenience, nothing else. I used to get roughly the same thing with "class SimpleNamespace: pass". :) FWIW, I proposed giving SimpleNamespace more exposure around the same time as PEP 421, and the reaction was lukewarm. [5] However, since then it's been used in several other places in the stdlib and I know of a few folks that have used it in their own projects. Regardless, ultimately the only reason I added it to the stdlib in the first place [6] was because it's the type of sys.implementation and it made more sense to expose it explicitly in the types module than implicitly via type(sys.implementation). -eric [1] https://www.python.org/dev/peps/pep-0421/#type-considerations [2] https://mail.python.org/pipermail/python-dev/2012-May/119771.html [3] https://mail.python.org/pipermail/python-dev/2012-May/119775.html [4] https://docs.python.org/3/library/types.html#types.SimpleNamespace [5] https://mail.python.org/pipermail/python-ideas/2012-May/015208.html [6] in contrast to argparse.Namespace and multiprocessing.managers.Namespace...

Chris Angelico <rosuav@...> writes:
I saw some proposals but forgot about them, thanks for the reminder. I'd prefer my proposal for two reasons: - the syntax is nicer that a factory function - it wouldn't be possible to add keyword arguments to __getitem__ without breaking compatibility Those issues are relatively minor, i'd be happy with a factory function
For all my use cases (not only function returns) I would completely replace namedtuple by anonymouns namedtuple.

On Tue, Apr 19, 2016 at 9:31 PM, Joseph Martinot-Lagarde <contrebasse@gmail.com> wrote:
Agreed, the syntax is a lot nicer - for this specific situation. Don't forget, though, that every piece of new syntax carries with it the not insignificant cost of complexity; and some things are better represented by function calls than syntax (cf 'print'). With "from types import SimpleNamespace as NS" at the top of your code, you can use the keyword-arguments form of the constructor to be almost the same as your proposal, without any new syntax. When a subsequent maintainer looks at your code, s/he can quickly look up at the imports to see what's going on, instead of having to learn another piece of syntax.
I have to agree. Fortunately it isn't hard to create a namedtuple factory: def NS(fields): return namedtuple('anonymous', fields.split()) or possibly: def NS(fields, *values): return namedtuple('anonymous', fields.split())(*values) That cuts down the duplication some, but it's far from perfect. ChrisA

Chris Angelico <rosuav@...> writes:
order
I agree on the principle, but to me this syntax looks less complex to me compared to the actual namedtuple where you have to use a factory to create a class to be able to use a namedtuple. And if you use a namedtuple as a return value, the definition of the namedtuple class will typically be relatively far away from the actual use of it. SimpleNamespace is nice but would break compatibility for return values.
It cuts down the duplication at the cost of readability. There is also the Matlab way which looks a bit better: from collections import namedtuple def NS(*args): fields = args[::2] values = args[1::2] return namedtuple('anonymous', fields)(*values) print(NS("x", 12, "y", 15)) But readability counts, and it's very easy to introduce bugs as adding or removing arguments can impact the whole chain. Initially coming from Matlab, the greatest interest I found in python was named arguments for functions! :)

On Tue, Apr 19, 2016 at 4:49 AM, Chris Angelico <rosuav@gmail.com> wrote:
Please don't recommend or spread this idiom! Every call to namedtuple() creates a new class, which is a very expensive operation. On my machine the simplest namedtuple call taks around 350 usec. -- --Guido van Rossum (python.org/~guido)

A general warning about this (x=12, y=16) idea: It's not so different from using dicts as cheap structs, constructing objects on the fly using either {'x': 12, 'y': 16} or dict(x=12, y=16). The problem with all these this is that if you use this idiom a lot, you're invariably going to run into cases where a field is missing, and you're spending a lot of time tracking down where the object was created incorrectly. Using a namedtuple (or any other construct that asks you to pre-declare the type used) the incorrect construction will cause a failure right at the point where it's being incorrectly constructed, making it much simpler to diagnose. In fully typed languages like Haskell or Java this wouldn't be a problem, but in languages like Python or Perl it is a real concern. -- --Guido van Rossum (python.org/~guido)

Guido van Rossum wrote:
If there were support from the compiler for a function def f(): return x=1, y=2 the namedtuple("_", "x y") class could be stored in f.__code__.co_consts just like 1 and 2. Adding information about the file and line number could probably be handled like it's done for code objects of classes and functions defined inside a function. While this approach still produces "late" failures debugging should at least be easier than for dict or SimpleNamespace instances.

Guido van Rossum <guido@...> writes: that if you use this idiom a lot, you're invariably going to run into cases where a field is missing, and you're spending a lot of time tracking down where the object was created incorrectly. Using a namedtuple (or any other construct that asks you to pre-declare the type used) the incorrect construction will cause a failure right at the point where it's being incorrectly constructed, making it much simpler to diagnose. I think that it depends a lot on what these are used for. What I primarily though about was to be able to easily return a namadtuple as a function output. In this case the namedtuple (anonymous or not) is created in a single place, so having to declare the namedtuple before using it has a limited interest, and has the drawbacks I presented before (code duplication, declaration far away from the use). What you're talking about is more like a container which would be used all around an application, where you need to ensure the corecntess of the struct everywhere. In this case a standard nametuple is a better fit. I feel like it's similar to the separation you talked about before, script vs application. My view is more script-like, yours is more application-like. Joseph

On Tue, Apr 19, 2016 at 12:06 PM, Guido van Rossum <guido@python.org> wrote:
Every call to namedtuple() creates a new class, which is a very expensive operation. On my machine the simplest namedtuple call taks around 350 usec.
Isn't that because the code for namedtuple is using exec instead a more pythonic approach of metaclassing to make it "faster" but taking longer to actually create the class? http://bugs.python.org/issue3974 Maybe instead of changing namedtuple (which seems to be a taboo), there could be a new anonymous type. Something built-in, with its own syntax

On Tue, Apr 19, 2016 at 9:58 AM, João Bernardo <jbvsmo@gmail.com> wrote:
That's part of it, but no matter how you do it, it's still creating a new class object, you can't get around that. And class objects are just expensive. Any idiom that ends up creating a new class object for each instance that's created is a big anti-pattern.
Maybe instead of changing namedtuple (which seems to be a taboo), there could be a new anonymous type. Something built-in, with its own syntax.
That's essentially what the (x=12, y=16) proposal is about, IIUC -- it would just be a single new type, so (x=12, y=16).__class__ would be the same class object as (a='', b=3.14). But I have serious reservations about that idiom too. -- --Guido van Rossum (python.org/~guido)

On 19.04.2016 19:35, Guido van Rossum wrote:
The proposal reminds me of JavaScript's "object". So, "(x=12, y=16).__class__ == type(object())"?
But I have serious reservations about that idiom too.
Me, too. I don't fully support this kind of on-the-fly construction as it is the same for closures. But that might just be my personal feeling because as such they escape proper testing and type support by IDEs (which reminds me strongly about Web development with JavaScript). On the other side, it allows ultra-rapid prototyping from which one can strip down to "traditional development" step by step when needed (using classes, tests etc.). This said, what are the reasons for your reservations? Best, Sven

On Tue, Apr 19, 2016 at 4:06 AM, Chris Angelico <rosuav@gmail.com> wrote:
FYI, PEP 468: "Preserving the order of **kwargs in a function." [1] The PEP exists for exactly the sort of use case being discussed here. In my case it was an alternate enum proposal I was making back when enums were under discussion. Regardless, I'd still like to see the PEP land. It's just a matter of finding time. I'll see if I can get some consensus leading up to and at PyCon next month. The actual implementation for PEP 468 is almost trivial. Now that we have a C-implementation of OrderedDict, it's mostly just a matter of addressing performance concerns [2], particularly those expressed by Guido, or falling back to one of the alternatives discussed in the PEP. Note that a related concept is represented with my work to make the class definition namespace ordered by default. [3] It would allow class decorators to have access to the order in which the class's attributes were defined. -eric [1] https://www.python.org/dev/peps/pep-0468/ [2] https://www.python.org/dev/peps/pep-0468/#performance [3] http://bugs.python.org/issue24254

This way they could be used in __getitem__ as proposed in PEP 472[0]
One of the link in this PEP is https://mail.python.org/pipermail/python-ideas/2013-June/021257.html where the writer raises some concerns about named tuples: - They pose problems with pickle because namedtuples needs subclasses to work. In my proposal it shouldn't be a problem anymore since there would be one class. - namedtuple() is a factory function requiring a 2-step initialization, a name, and a subclass. Again it disappears in my proposal. I'm not sure about the database problem since I don't use them.

On Tue, Apr 19, 2016 at 09:49:44AM +0000, Joseph Martinot-Lagarde wrote:
You aren't forced to declare the type ahead of time, you can just use it as part of an expression: py> from collections import namedtuple py> my_tuple = namedtuple("_", "x y z")(1, 2, 3) py> print(my_tuple) _(x=1, y=2, z=3) However, there is a gotcha if you do this: each time you create an anonymous namedtuple, you create a new, distinct, class: py> a = namedtuple("_", "x y")(1, 2) py> b = namedtuple("_", "x y")(1, 2) py> type(a) == type(b) False which could be both surprising and expensive. One possible solution: keep your own cache of classes: def nt(name, fields, _cache={}): cls = _cache.get((name, fields), None) if cls is None: cls = _cache[(name, fields)] = namedtuple(name, fields) return cls
The name is not useless. It is very useful for string representations, debugging, introspection, and generally having a clue what the object represents. How else do you know what kind of object you are dealing with? I agree that it is a little sad that we have to repeat the name twice, but strictly speaking, you don't even need to do that. For example: class Point(namedtuple("AbstractPoint", "x y z")): def method(self): ... In my opinion, avoiding having to repeat the name twice is a "nice to have", not a "must have".
How do you know that the 0th item is field "x"? Keyword arguments are not ordered. Even if you could somehow determine the order that they are given, you can't use that information since we should expect that: assert (x=12, y=16) == (y=16, x=12) will pass. (Why? Because they're keyword arguments, and the order of keyword arguments shouldn't matter.) So we have a problem that the indexing order (the same order is used for iteration and tuple unpacking) is not specified anywhere. This is a *major* problem for an ordered type like tuple. namedtuple avoids this problem by requiring the user to specify the field name order before creating an instance. SimpleNamespace avoids this problem by not being ordered or iterable. I suppose we could put the fields in sorted order. But that's going to make life difficult for uses where we would like some other order, e.g. to match common conventions. Consider a 3D point in spherical coordinates: pt = (r=3, theta=0.5, phi=0.25) In sorted order, pt == (3, 0.25, 0.5) which goes against the standard mathematical definition. Namedtuples pre-define what fields are allowed, what they are called, and what order they appear in. Anonymous namedtuples as you describe them don't do any of these things. Consider that since they're tuples, we should be able to provide the items as positional arguments to the construct, just like regular namedtuples: pt = (x=12, y=16) type(pt)(1, 2) This works fine with namedtuple, but how will it work with your proposal? And what happens if we do this? type(pt)(1, 2, 3) And of course, a naive implementation would suffer from the same issue as mentioned above, where every instance is a singleton of a distinct class. Python isn't a language where we care too much about memory use, but surely we don't want to be quite this profligate: py> a = namedtuple("Point", "x y z")(1, 2, 3) py> sys.getsizeof(a) # reasonably small 36 py> sys.getsizeof(type(a)) # not so small 420 Obviously we don't want every instance to belong to a distinct class, so we need some sort of cache. SimpleNamespace solves this problem by making all instances belong to the same class. That's another difference between namedtuple and what you seem to want. -- Steve

Steven D'Aprano <steve@...> writes:
This looks nice with a short number of short attribute names, but in a real case separating the values from their corresponding field hurts readability. Compare: my_tuple = namedtuple("_", "site, gisement, range_nominal, range_bista, is_monostatic")(12.45, 45.0, 3000.0, 2998.5357, True) my_tuple = (site=12.45, gisement=45.0, range_nominal=3000.0, range_bista=2998.5357, is_monostatic=True) As a side note, if the empty string would be allowed for the class name the printed value would look better. The fact that it's not possible right now looks liek an implementation "detail".
Of course he name is not completely useless, but you can often know what a namedtuple represents in your application or your script from the field names only (or the variable name). SimpleNamespace live very well without a name, for example.
In my proposal these are not keywords arguments, they are a syntax construct to build a anonymous namedtuple. That's why I can't just create a factory function. The order is determiend by the construction, and can be found by introspection (simply printing the object will do). I suppose that as a developper it's a shift from how keywords behave now, but as a user a namedtuple is still a tuple, and it keeps the ordering.
They inherits tuples, that doesn't mean that they behave in all cases like tuples. In that case I guess that this form would not be allowed. I don't know how bad this looks for a python dev though!
Yes, that's another difference, I don't want to replicate namedtuples exactly (otherwise I'd just use a namedtuple). I don't think that you need a cache, more like a frozendict per instance which binds the fields to the corresponding index. Maybe it's what you call cache ?
participants (12)
-
Chris Angelico
-
Eric Snow
-
Ethan Furman
-
Guido van Rossum
-
Joseph Martinot-Lagarde
-
João Bernardo
-
Koos Zevenhoven
-
Paul Moore
-
Peter Otten
-
Random832
-
Steven D'Aprano
-
Sven R. Kunze