Style qeustion: Multiple return values
Just a short style question: When returning multiple return values, do you use parenthesis? E.g. would you write def foo(): return 1, 2 a, b = foo() or do you prefer def foo(): return (1, 2) (a, b) = foo() Steve -- https://mail.python.org/mailman/listinfo/python-list
Different "look and feel" of some built-in functions
Why do some built-in Python functions feel so differently: For example sum(), all(), any() expect exactly one argument which is a sequence to operate on, i.e. a list, an iterator or a generator etc. sum([1,2,3,4]) sum(range(1, 101)) sum(2**i for i in range(10)) all([True, False]) any(even, {1,2,3,4}) while other functions like set.union() and set.intersection() work on a list of arguments but not on a sequence: set.intersection({1,2,3}, {3,4,5}) but set.union(map(...)) # does not work set.intersection(list(...)) # does not work and you have to use a * instead set.union(*map(...)) etc. Is this just for historical reason? And wouldn't it be possible and desirable to have more consistency? Steve -- https://mail.python.org/mailman/listinfo/python-list
Re: Different "look and feel" of some built-in functions
"Dieter Maurer" writes: > Steve Keller wrote at 2021-9-24 11:48 +0200: > >Why do some built-in Python functions feel so differently: > > Because the typical use cases are different > > [...] > > >while other functions like set.union() and set.intersection() work on > >a list of arguments but not on a sequence: > > > >set.intersection({1,2,3}, {3,4,5}) > > Those operations are typically applied to a small number > of operands. You would need to build an iterator in that > case should the functions only accept iterators. In my experience I need intersection and union on a list of sets, set of sets or a map() returning sets much more often. E.g. in some mathematical problems, and in automaton theory (IIRC, computing of LR or LALR sets, converting NFA to DFA, minimizing DFA), many graph algorithms traversing the nodes (shortest path, ...), and so on). Intersection and union of two sets is actually often seen in naïve programming in loops like for t in (some_sequence): s.union(t) where set.union(*(some_sequence)) would be much more elegant. BTW, I like how the min() and max() functions allow both ways of being called. Steve -- https://mail.python.org/mailman/listinfo/python-list
sum() vs. loop
I have found the sum() function to be much slower than to loop over the operands myself: def sum_products(seq1, seq2): return sum([a * b for a, b in zip(seq1, seq2)]) def sum_products2(seq1, seq2): sum = 0 for a, b in zip(seq1, seq2): sum += a * b return sum In a program I generate about 14 million pairs of sequences of ints each of length 15 which need to be summed. The first version with sum() needs 44 seconds while the second version runs in 37 seconds. Can someone explain this difference? Steve -- https://mail.python.org/mailman/listinfo/python-list
Re: sum() vs. loop
Christian Gollwitzer writes: > > def sum_products(seq1, seq2): > > return sum([a * b for a, b in zip(seq1, seq2)]) > > def sum_products2(seq1, seq2): > > sum = 0 > > for a, b in zip(seq1, seq2): > > sum += a * b > > return sum > > [...] > > The first version constructs a list, sums it up and throws the list > away, while the second version only keeps the running sum in > memory. How about a generator expression instead, i.e. > > > sum((a * b for a, b in zip(seq1, seq2))) Ah, of course. Much cleaner and I should have seen that myself. Thanks. BUT > (untested) ? I have tested it and with () instead of [] it's even slower: explicit loop: 37s ± .5s sum([...]) 44s ± .5s sum((...)) 47.5s ± .5s Now completely surprised. Steve -- https://mail.python.org/mailman/listinfo/python-list
Why do integers compare equal to booleans?
Why do the integers 0 and 1 compare equal to the boolean values False and True and all other integers to neither of them? $ python3 Python 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> 0 == False True >>> 1 == True True >>> 2 == False False >>> 2 == True False >>> -1 == False False >>> -1 == True False >>> Since these are objects of different types I would expect they cannot be equal. I know that 0 means false and != 0 means true in C, C++, etc. but in Python that surprises me. Steve -- https://mail.python.org/mailman/listinfo/python-list
Generators, generator expressions, and loops
I have looked at generators, generator expressions, and iterators and I try to get more familiar with these. 1. How would I loop over all (with no upper bound) integers or all powers of two, for example? In C it would be for (int i = 0; ; i++) { ... } or for (int i = 1; ; i *= 2) { ... } In Python, I could define a generator def powers(): i = 1 while True: yield(i) i *= 2 for i in powers(): ... More elegant are generator expressions but I cannot think of a way without giving an upper limit: for i in (2 ** i for i in range(100)): ... which looks ugly. Also, the double for-loop (and also the two loops in the above exmaple, for + while in the generator) look unnatural, somehow, i.e. loop over all elements which are created by a loop. Is there a more beautyful way? Steve -- https://mail.python.org/mailman/listinfo/python-list
Generators, generator expressions, and loops
I have looked at generators, generator expressions, and iterators and I try to get more familiar with these. 1. How would I loop over all (with no upper bound) integers or all powers of two, for example? In C it would be for (int i = 0; ; i++) { ... } or for (int i = 1; ; i *= 2) { ... } In Python, I could define a generator def powers(): i = 1 while True: yield(i) i *= 2 for i in powers(): ... More elegant are generator expressions but I cannot think of a way without giving an upper limit: for i in (2 ** i for i in range(100)): ... which looks ugly. Also, the double for-loop (and also the two loops in the above exmaple, for + while in the generator) look unnatural, somehow, i.e. loop over all elements which are created by a loop. Is there a more beautyful way? Steve -- https://mail.python.org/mailman/listinfo/python-list
Iterators of iterators
I wonder why iterators do have an __iter__() method? I thought iterable objects would have an __iter__() method (but no __next__()) to create an iterator for it, and that would have the __next__() method but no __iter__(). $ python3 Python 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> l = [1,2,3] >>> next(l) Traceback (most recent call last): File "", line 1, in TypeError: 'list' object is not an iterator This is expected, of course. >>> iter(l) >>> iter(iter(l)) >>> iter(iter(iter(l))) >>> i = iter(iter(iter(l))) >>> list(i) [1, 2, 3] Is there any reason or usage for this? Steve -- https://mail.python.org/mailman/listinfo/python-list
Generators, generator expressions, and loops
Cancel ill-formated article -- https://mail.python.org/mailman/listinfo/python-list
Animated functions with matplotlib
I am trying to plot a live signal using matplotlib and it really drives me crazy. I have tried dozens of variants, with and without interactive (plt.ion()), with animation.FuncAnimation and doing things by hand, calling plt.show() and/or plt.draw() but nothing works as expected. One problem is that running commands in the interactive python shell behaves differently from the behavior when using the same commands in a script, so trying out different versions is very confusing. I'd like to do something like this: fig, ax = plt.subplots() ival = .1 now = 0 t = list(numpy.linspace(now, now, 500)) y = [0] * len(t) while True: time.sleep(ival) now += ival val = get_sample_from_some_signal() t = t[1:] + [now] y = y[1:] + [val] ax.clear() ax.plot(t, y) plt.pause(1e-9) This works but is *very* slow and it seems the plot window is closed and opened again or raised for each new value to plot. I have tried to call plt.show(block=False) only once and then repeatedly only change data with ax.lines[0].set_xdata(), ax.lines[0].set_ydata(), and ax.set_xlim() and then calling plt.draw(). That works in the interactive python shell but not in a script. When calling set[xy]_data() and set_xlim() in an amimate() function passed to animation.FuncAnimation, but I haven't managed to redraw the x scale values (although ax.xlim() is called). Also, with animation.FuncAnimation() I loose control of the main thread of execution. When calling plt.show() the function doesn't return. I may want to change the loop so that instead of time.sleep(ival) val = get_sample_from_some_signal() I would have val = wait_for_next_same_from_some_signal() and I think this doesn't work with FuncAnimation since that calls the passed function with a fixed time interval. I am completely lost, can someone help? Steve -- https://mail.python.org/mailman/listinfo/python-list