[issue34719] Deprecate set to frozenset conversion in set.__contains__
New submission from Javier Dehesa : This comes from this SO question: https://stackoverflow.com/q/52382983/1782792 Currently, this works: > print({1, 2} in {frozenset({1, 2})) # True This is strange because set is unhashable. Apparently, it is a case-specific feature implemented back in 2003 (https://github.com/python/cpython/commit/19c2d77842290af9b5f470c1eea2a71d1f77c9fe), by which set objects are converted to frozensets when checking for membership in another set. Personally I feel this is a bit surprising and inconsistent, but that is not the only issue with it. In the original implementation, this conversion was basically free because the created frozenset used the same storage as the given one. In the current implementation, however (https://github.com/python/cpython/blob/3.7/Objects/setobject.c#L1888-L1906), a new frozenset object is created, copied from the previous one. It seems this was done for thread-safety. The problem with that is that it is significantly more expensive: s = set(range(10)) sf = frozenset(s) t = { sf } %timeit sf in t # True >>> 31.6 ns ± 1.04 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit s in t # True >>> 4.9 ms ± 168 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) In the above case, using the conversion takes five order of magnitude more time than the regular check. I suppose there is a memory impact too. I think this (as far as I know) undocumented feature does not provide a significant usability gain, is inconsistent with the documented behavior of set and gives rise to obscurely underperfoming code. Removing it would be a breaking change, but again, affected code would be relying on undocumented behavior (or even "against-documentation" behavior). -- components: Interpreter Core messages: 325631 nosy: Javier Dehesa priority: normal severity: normal status: open title: Deprecate set to frozenset conversion in set.__contains__ type: behavior versions: Python 2.7, Python 3.4, Python 3.5, Python 3.6, Python 3.7, Python 3.8 ___ Python tracker <https://bugs.python.org/issue34719> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue33214] join method for list and tuple
Javier Dehesa <javi...@gmail.com> added the comment: Thanks Christian. I thought of join precisely because it performs conceptually the same function as with str, so the parallel between ''.join(), [].join() and ().join() looked more obvious. Also there is os.path.join and PurePath.joinpath, so the verb seemed well-established. As for shared method names, index and count are present both in sequences and str - although it is true that these do return the same kind of object in any cases. I'm not saying your points aren't valid, though. Your proposed way with extend is I guess about the same as list(itertools.chain(...)), which could be considered to be enough. I just feel that is not particularly convenient, especially for newer developers, which will probably gravitate towards sum(...) more than itertools or a nested generator expression, but I may be wrong. -- ___ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue33214> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue33214] join method for list and tuple
New submission from Javier Dehesa <javi...@gmail.com>: It is pretty trivial to concatenate a sequence of strings: ''.join([str1, str2, ...]) Concatenating a sequence of lists is for some reason significantly more convoluted. Some current options include: sum([lst1, lst2, ...], []) [x for y [lst1, lst2, ...] for x in y] list(itertools.chain(lst1, lst2, ...)) The first one being the less recomendable but more intuitive and the third one being the faster but most cumbersome (see https://stackoverflow.com/questions/49631326/why-is-itertools-chain-faster-than-a-flattening-list-comprehension ). None of these looks like "the one obvious way to do it" to me. Furthermore, I feel a dedicated concatenation method could be more efficient than any of these approaches. If we accept that ''.join(...) is an intuitive idiom, why not provide the syntax: [].join([lst1, lst2, ...]) And while we are at it: ().join([tpl1, tpl2, ...]) Like with str, these methods should only accept sequences of objects of their own class (e.g. we could do [].join(list(s) for s in seqs) if seqs contains lists, tuples and generators). The use case for non-empty joiners would probably be less frequent than for strings, but it also solves a problem that has no clean solution with the current tools. Here is what I would probably do to join a sequence of lists with [None, 'STOP', None]: lsts = [lst1, lst2, ...] joiner = [None, 'STOP', None] lsts_joined = list(itertools.chain.from_iterable(lst + joiner for lst in lsts))[:-len(joiner)] Which is awful and inefficient (I am not saying this is the best or only possible way to solve it, it is just what I, self-considered experienced Python developer, might write). -- components: Library (Lib) messages: 314881 nosy: Javier Dehesa priority: normal severity: normal status: open title: join method for list and tuple type: enhancement ___ Python tracker <rep...@bugs.python.org> <https://bugs.python.org/issue33214> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue30678] Widget variable binding does not work if mainloop is called from a different function
Javier Dehesa added the comment: With the additional hint of garbage collection I have found now a number of examples of this behaviour (e.g. https://stackoverflow.com/questions/7439432/python-themed-tkinter-entry-variable-will-not-set). However, I haven't found actual documentation warning of this, so I'm not sure if this is really expected or just something people has gotten used to live with. One could argue that you normally wouldn't need a variable in the first place if you are not keeping a reference to it, but I'm not sure what is the benefit of having a (I assume) weak reference in the widget. Maybe there are solid technical reasons but, from what I have seen, it seems to have caused more than one confusion. -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue30678> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue30678] Widget variable binding does not work if mainloop is called from a different function
Javier Dehesa added the comment: I see what you mean. Looking at TkDocs (not sure if this is an "official" or "officially endorsed" source or not), one of the Python examples in the "Tk Concepts" section (http://www.tkdocs.com/tutorial/concepts.html) says: > Whether or not you save the widget object in a variable is entirely up to > you, and depends of course whether you'll need to refer to it later. Because > the object is inserted into the widget hierarchy, it won't be garbage > collected even if you don't keep your own reference to it. However, it very much looks like it may be related to what you said. -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue30678> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue30678] Widget variable binding does not work if mainloop is called from a different function
Javier Dehesa added the comment: Yeah is quite subtle, I should have pointed it out... The difference is that `root.mainloop()` is called inside `make_var_cb(root)` in the first example and under `if __name__ == '__main__'` in the second one. I have experience the problem on Windows 10, and I'd say there is a good chance it's a platform-specific thing... -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue30678> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue30678] Widget variable binding does not work if mainloop is called from a different function
Javier Dehesa added the comment: Note, this is not something specific to check buttons, the same happens with other widgets such as entries. -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue30678> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue30678] Widget variable binding does not work if mainloop is called from a different function
New submission from Javier Dehesa: When you build a Tkinter interface with variables, if tkinter.Tk.mainloop is called from a different function that the one creating the variable objects, then in some cases the widgets associated with the variables will not be set to the right value. I have not been able to find a consistent pattern, but I have some examples. The following script works correctly: ``` import tkinter as tk from tkinter import ttk def make_var_cb(root): v = tk.BooleanVar(root, True) cb = ttk.Checkbutton(root, text='Checkbutton', variable=v) cb.pack() root.mainloop() if __name__ == '__main__': root = tk.Tk() make_var_cb(root) ``` But the following does not (the result is shown in the attached image): ``` import tkinter as tk from tkinter import ttk def make_var_cb(root): v = tk.BooleanVar(root, True) cb = ttk.Checkbutton(root, text='Checkbutton', variable=v) cb.pack() if __name__ == '__main__': root = tk.Tk() make_var_cb(root) root.mainloop() ``` However, the following _does_ work again: ``` def make_var(root): return tk.BooleanVar(root, True) def make_cb(root, v): return ttk.Checkbutton(root, text='Checkbutton', variable=v) if __name__ == '__main__': root = tk.Tk() v = make_var(root) cb = make_cb(root, v) cb.pack() root.mainloop() ``` -- components: Tkinter, Windows files: checkbutton_bad.png messages: 296100 nosy: Javier Dehesa, paul.moore, steve.dower, tim.golden, zach.ware priority: normal severity: normal status: open title: Widget variable binding does not work if mainloop is called from a different function type: behavior versions: Python 3.5 Added file: http://bugs.python.org/file46954/checkbutton_bad.png ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue30678> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com