[Python-Dev] Re: PEP 618: Add Optional Length-Checking To zip
On Mon, Jun 01, 2020 at 09:36:40PM +1000, Nick Coghlan wrote: > zip() can be used to combine iterables of different lengths, including > combining finite iterables with infinite iterators. By default, the output > iterator is implicitly truncated to produce the same number of items as the > shortest input iterable. Setting *truncate* to false disables this implicit > truncation and raises ValueError instead. It's not really *implicit* if there's an explicit flag controlling the behaviour, even with a default value. We don't use that sort of language elsewhere. For example, help(sorted) doesn't say: "Return a new list containing all items from the iterable implicitly in ascending order. Pass reverse=True to disable this implicit order." help(int) doesn't say that the base is implicitly decimal; help(print) doesn't talk about "implicit spaces between items, implicit newline at the end of the output" etc. It just states the behaviour controlled by the parameter. This is accurate, non-judgemental, and avoids being over-wordy: "By default, the output iterator is truncated at the shortest input iterable." > The conceptual idea here is that the "truncate" flag name would technically > be a shorter mnemonic for "truncate_silently", so clearing it gives you an > exception rather enabling padding behaviour. > > Flipping the sense of the flag also means that "truncate=True" will appear > in IDE tooltips as part of the function signature, providing significantly > more information than "strict=False" would. "Significantly" more? I don't think so. Truncate at what? - some maximum length; - some specific element; - at the shortest input. At some point people have to read the docs, not just the tooltips. If you didn't know what zip does, seeing truncate=True won't mean anything to you. If you do know what zip does, then the parameter names are mnemonics, and strict=False and truncate=True provide an equal hint for the default behaviour: * if it's not strict, it is tolerant, stopping at the shortest; * if it truncates, it truncates at the shortest input. For the default case, strict=False and truncate=True are pretty much equal in information. But for the case of non-default behaviour, strict=True is a clear winner. It can pretty much only mean one thing: raise an exception. Whereas truncate=False is ambiguous: - pad the output; - skip items as they become empty; - raise an exception. All three of these are useful behaviour, and while the middle one is not part of this PEP, it was requested in the discussions on Python-Ideas. > That improved self-documentation then becomes what I would consider the > strongest argument in favour of the flag-based approach: I don't think that "truncate=False" (which can mean three different things) is more self-documenting than `zip(*items, mode='strict')` or `zip_strict()` (either of which can only mean one thing). -- Steven ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/37TI3ZEU7JZUJBERFDRRCMNI5Y3CGP7T/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: type() does not call __prepare__?
But on calling `type` in this way, you are passing the namespace as a ready object, as the 3rdy parameter - what would `__prepare__` even do, besides print it's been called? For sometime (maybe Python 3.3, I forgot), some helper callables where added to the `types` module to allow one to have more freedom in imperatively created classes: python In [20]: types.prepare_class? Signature: types.prepare_class(name, bases=(), kwds=None) Docstring: Call the __prepare__ method of the appropriate metaclass. Returns (metaclass, namespace, kwds) as a 3-tuple *metaclass* is the appropriate metaclass *namespace* is the prepared class namespace *kwds* is an updated copy of the passed in kwds argument with any 'metaclass' entry removed. If no kwds argument is passed in, this will be an empty dict. File: ~/projetos/terminedia/env/lib64/python3.7/types.py Type: function In [21]: types.new_class? Signature: types.new_class(name, bases=(), kwds=None, exec_body=None) Docstring: Create a class object dynamically using the appropriate metaclass. File: ~/projetos/terminedia/env/lib64/python3.7/types.py Type: function In [22]: types.resolve_bases? Signature: types.resolve_bases(bases) Docstring: Resolve MRO entries dynamically as specified by PEP 560. File: ~/projetos/terminedia/env/lib64/python3.7/types.py Type: function ``` On Mon, 1 Jun 2020 at 16:28, Ethan Furman wrote: > > From stackoverflow [1] > ># metaprepare.py >class Meta1(type): >@classmethod >def __prepare__(mcs, name, bases): >print('call prepare') >return {} >def __new__(mcs, name, bases, parameters): >return super().__new__(mcs, name, bases, parameters) > >class A(metaclass=Meta1): >pass > >type('C', (A, ), {}) > > output is: > >call prepare > > (just the once, not twice) > > The behavior of `type()` not calling `__prepare__()` has been constant since > 3.3. > > Is it a bug? > > > -- > ~Ethan~ > > > [1] https://stackoverflow.com/q/62128254/208880 > ___ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/CQTD7WFOIDBF5PSD77AALBTWJQ67UPM5/ > Code of Conduct: http://python.org/psf/codeofconduct/ ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/IPBWREEI6JYGWROTSXGHBWLG53Q4A23A/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Repr: where to place the address and additional info?
Serhiy Storchaka wrote: > The default repr of Python object is formatted using the following pattern: > <{typename} object at {address:#x}> > > And many custom reprs use similar patterns, but add some additional type > specific information. The type name first, followed by details and > address. All is surrounded by angle quotes. The question is in what > order to show address and other details? Should the address be at rear > or in the middle? > <{typename} {details} at {address:#x}> > <{typename} at {address:#x} {details}> I prefer the address at the rear. Chances are you care more about the details than the address, so put the more useful information earlier. > > There are examples of both ways in the stdlib. I am going to add new > custom reprs [1] and need to know what pattern looks better. > Also, is "object" mandatory after the type name? > <{typename} object {details} at {address:#x}> > <{typename} object at {address:#x} {details}> I don't think it's mandatory. Whatever reads best. -Brett > > [1] https://bugs.python.org/issue24391 ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/OY7UZGXEU32ACL7HOPI7RLGCOJEMTF5K/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] type() does not call __prepare__?
From stackoverflow [1] # metaprepare.py class Meta1(type): @classmethod def __prepare__(mcs, name, bases): print('call prepare') return {} def __new__(mcs, name, bases, parameters): return super().__new__(mcs, name, bases, parameters) class A(metaclass=Meta1): pass type('C', (A, ), {}) output is: call prepare (just the once, not twice) The behavior of `type()` not calling `__prepare__()` has been constant since 3.3. Is it a bug? -- ~Ethan~ [1] https://stackoverflow.com/q/62128254/208880 ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/CQTD7WFOIDBF5PSD77AALBTWJQ67UPM5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 618: Add Optional Length-Checking To zip
On 06/01/2020 04:36 AM, Nick Coghlan wrote: Reading this thread and the current PEP, the main question I had was whether it might be better to flip the sense of the flag and call it "truncate". So the status quo would be "truncate=True", while the ValueError could be requested by passing an explicit "truncate=False". I like this a lot. +1 -- ~Ethan~ ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/TQWWOQM4MQZ4T5CPZB3D4XPQ5HKIVFEP/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: PEP 618: Add Optional Length-Checking To zip
On Thu., 21 May 2020, 4:09 am Jim J. Jewett, wrote: > David Mertz wrote: > > > Fwiw, I don't think it changes my order, but 'strict' is a better word > than > > 'equal' in all those places. I'd subtract 0.1 from each of those votes if > > they used "equal". > > I would say that 'equal' is worse than 'strict'. but 'strict' is also > wrong. > > Zipping to a potentially infinite sequence -- like a manual enumerate -- > isn't wrong. It may be the less common case, but it isn't wrong. Using > 'strict' implies that there is something sloppy about the data in, for > example, cases like Stephen J. Turnbull's lagged time series. > > Unfortunately, the best I can come up with is 'same_length', or possibly > 'equal_len' or 'equal_length'. While those are better semantically, they > are also slightly too long or awkward. I would personally still consider > 'same_length' the least bad option. > Reading this thread and the current PEP, the main question I had was whether it might be better to flip the sense of the flag and call it "truncate". So the status quo would be "truncate=True", while the ValueError could be requested by passing an explicit "truncate=False". Draft documentation paragraph: == zip() can be used to combine iterables of different lengths, including combining finite iterables with infinite iterators. By default, the output iterator is implicitly truncated to produce the same number of items as the shortest input iterable. Setting *truncate* to false disables this implicit truncation and raises ValueError instead. Note that if this ValueError is raised an additional item will have been consumed from any iterators listed before the shortest iterator (or from the second listed iterator if the first iterator is the shortest one). To pad shorter input iterables rather than truncating the output or raising ValueError, see itertools.zip_longest. == The conceptual idea here is that the "truncate" flag name would technically be a shorter mnemonic for "truncate_silently", so clearing it gives you an exception rather enabling padding behaviour. Flipping the sense of the flag also means that "truncate=True" will appear in IDE tooltips as part of the function signature, providing significantly more information than "strict=False" would. That improved self-documentation then becomes what I would consider the strongest argument in favour of the flag-based approach: providing more information up-front to users regarding the actual behaviour of the builtin, rather than having them incorrectly assume that mismatched input iterator lengths will raise an exception. Side note: this idea pairs nicely with the "zip(itr, itr, ir)" idiom for non-overlapping data windows, as it makes it straightforward to request an exception if the last data tuple has values missing (without the flag, the idiom silently discards incomplete trailing data). Cheers, Nick. P.S. I had the opportunity to read the thread from beginning to end after belatedly catching some of the messages out of context, and FWIW, I started out assuming I would strongly favour the itertools function option, and surprised myself by favouring the flag option (albeit inverted) by the time I reached the end. > ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/MBLEKMSJOVHPH64GDTE4LZA2Z5TTZKAC/ Code of Conduct: http://python.org/psf/codeofconduct/