[issue34719] Deprecate set to frozenset conversion in set.__contains__

2018-09-18 Thread Javier Dehesa

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

2018-04-03 Thread Javier Dehesa

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

2018-04-03 Thread Javier Dehesa

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

2017-06-16 Thread Javier Dehesa

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

2017-06-16 Thread Javier Dehesa

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

2017-06-16 Thread Javier Dehesa

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

2017-06-16 Thread Javier Dehesa

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

2017-06-15 Thread Javier Dehesa

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