Skip to content

Commit 85d9f47

Browse files
author
NGRsoftlab
authored
Merge branch 'main' into fix-issue-116180
2 parents 259034c + ba82a24 commit 85d9f47

File tree

147 files changed

+1919
-571
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

147 files changed

+1919
-571
lines changed

.github/workflows/stale.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Mark stale pull requests
22

33
on:
44
schedule:
5-
- cron: "0 0 * * *"
5+
- cron: "0 */12 * * *"
66

77
permissions:
88
pull-requests: write

Doc/faq/design.rst

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,11 @@ is evaluated in all cases.
259259
Why isn't there a switch or case statement in Python?
260260
-----------------------------------------------------
261261

262-
You can do this easily enough with a sequence of ``if... elif... elif... else``.
263-
For literal values, or constants within a namespace, you can also use a
264-
``match ... case`` statement.
262+
In general, structured switch statements execute one block of code
263+
when an expression has a particular value or set of values.
264+
Since Python 3.10 one can easily match literal values, or constants
265+
within a namespace, with a ``match ... case`` statement.
266+
An older alternative is a sequence of ``if... elif... elif... else``.
265267

266268
For cases where you need to choose from a very large number of possibilities,
267269
you can create a dictionary mapping case values to functions to call. For
@@ -290,6 +292,9 @@ It's suggested that you use a prefix for the method names, such as ``visit_`` in
290292
this example. Without such a prefix, if values are coming from an untrusted
291293
source, an attacker would be able to call any method on your object.
292294

295+
Imitating switch with fallthrough, as with C's switch-case-default,
296+
is possible, much harder, and less needed.
297+
293298

294299
Can't you emulate threads in the interpreter instead of relying on an OS-specific thread implementation?
295300
--------------------------------------------------------------------------------------------------------

Doc/faq/extending.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ to learn Python's C API.
5050
If you need to interface to some C or C++ library for which no Python extension
5151
currently exists, you can try wrapping the library's data types and functions
5252
with a tool such as `SWIG <https://www.swig.org>`_. `SIP
53-
<https://riverbankcomputing.com/software/sip/intro>`__, `CXX
53+
<https://github.com/Python-SIP/sip>`__, `CXX
5454
<https://cxx.sourceforge.net/>`_ `Boost
5555
<https://www.boost.org/libs/python/doc/index.html>`_, or `Weave
5656
<https://github.com/scipy/weave>`_ are also

Doc/glossary.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -841,10 +841,11 @@ Glossary
841841
Some named tuples are built-in types (such as the above examples).
842842
Alternatively, a named tuple can be created from a regular class
843843
definition that inherits from :class:`tuple` and that defines named
844-
fields. Such a class can be written by hand or it can be created with
845-
the factory function :func:`collections.namedtuple`. The latter
846-
technique also adds some extra methods that may not be found in
847-
hand-written or built-in named tuples.
844+
fields. Such a class can be written by hand, or it can be created by
845+
inheriting :class:`typing.NamedTuple`, or with the factory function
846+
:func:`collections.namedtuple`. The latter techniques also add some
847+
extra methods that may not be found in hand-written or built-in named
848+
tuples.
848849

849850
namespace
850851
The place where a variable is stored. Namespaces are implemented as

Doc/library/itertools.rst

Lines changed: 138 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -902,18 +902,19 @@ which incur interpreter overhead.
902902
# iter_index('AABCADEAF', 'A') --> 0 1 4 7
903903
seq_index = getattr(iterable, 'index', None)
904904
if seq_index is None:
905-
# Slow path for general iterables
905+
# Path for general iterables
906906
it = islice(iterable, start, stop)
907907
for i, element in enumerate(it, start):
908908
if element is value or element == value:
909909
yield i
910910
else:
911-
# Fast path for sequences
911+
# Path for sequences with an index() method
912912
stop = len(iterable) if stop is None else stop
913-
i = start - 1
913+
i = start
914914
try:
915915
while True:
916-
yield (i := seq_index(value, i+1, stop))
916+
yield (i := seq_index(value, i, stop))
917+
i += 1
917918
except ValueError:
918919
pass
919920

@@ -931,31 +932,25 @@ which incur interpreter overhead.
931932
# grouper('ABCDEFG', 3, fillvalue='x') --> ABC DEF Gxx
932933
# grouper('ABCDEFG', 3, incomplete='strict') --> ABC DEF ValueError
933934
# grouper('ABCDEFG', 3, incomplete='ignore') --> ABC DEF
934-
args = [iter(iterable)] * n
935+
iterators = [iter(iterable)] * n
935936
match incomplete:
936937
case 'fill':
937-
return zip_longest(*args, fillvalue=fillvalue)
938+
return zip_longest(*iterators, fillvalue=fillvalue)
938939
case 'strict':
939-
return zip(*args, strict=True)
940+
return zip(*iterators, strict=True)
940941
case 'ignore':
941-
return zip(*args)
942+
return zip(*iterators)
942943
case _:
943944
raise ValueError('Expected fill, strict, or ignore')
944945
945946
def roundrobin(*iterables):
946947
"Visit input iterables in a cycle until each is exhausted."
947948
# roundrobin('ABC', 'D', 'EF') --> A D E B F C
948-
# Recipe credited to George Sakkis
949-
num_active = len(iterables)
950-
nexts = cycle(iter(it).__next__ for it in iterables)
951-
while num_active:
952-
try:
953-
for next in nexts:
954-
yield next()
955-
except StopIteration:
956-
# Remove the iterator we just exhausted from the cycle.
957-
num_active -= 1
958-
nexts = cycle(islice(nexts, num_active))
949+
# Algorithm credited to George Sakkis
950+
iterators = map(iter, iterables)
951+
for num_active in range(len(iterables), 0, -1):
952+
iterators = cycle(islice(iterators, num_active))
953+
yield from map(next, iterators)
959954
960955
def partition(predicate, iterable):
961956
"""Partition entries into false entries and true entries.
@@ -996,10 +991,10 @@ The following recipes have a more mathematical flavor:
996991
s = list(iterable)
997992
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
998993

999-
def sum_of_squares(it):
994+
def sum_of_squares(iterable):
1000995
"Add up the squares of the input values."
1001-
# sum_of_squares([10, 20, 30]) -> 1400
1002-
return math.sumprod(*tee(it))
996+
# sum_of_squares([10, 20, 30]) --> 1400
997+
return math.sumprod(*tee(iterable))
1003998
1004999
def reshape(matrix, cols):
10051000
"Reshape a 2-D matrix to have a given number of columns."
@@ -1019,17 +1014,16 @@ The following recipes have a more mathematical flavor:
10191014

10201015
def convolve(signal, kernel):
10211016
"""Discrete linear convolution of two iterables.
1017+
Equivalent to polynomial multiplication.
10221018

1023-
The kernel is fully consumed before the calculations begin.
1024-
The signal is consumed lazily and can be infinite.
1025-
1026-
Convolutions are mathematically commutative.
1027-
If the signal and kernel are swapped,
1028-
the output will be the same.
1019+
Convolutions are mathematically commutative; however, the inputs are
1020+
evaluated differently. The signal is consumed lazily and can be
1021+
infinite. The kernel is fully consumed before the calculations begin.
10291022

10301023
Article: https://betterexplained.com/articles/intuitive-convolution/
10311024
Video: https://www.youtube.com/watch?v=KuXjwB4LzSA
10321025
"""
1026+
# convolve([1, -1, -20], [1, -3]) --> 1 -4 -17 60
10331027
# convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
10341028
# convolve(data, [1/2, 0, -1/2]) --> 1st derivative estimate
10351029
# convolve(data, [1, -2, 1]) --> 2nd derivative estimate
@@ -1067,7 +1061,7 @@ The following recipes have a more mathematical flavor:
10671061
f(x) = x³ -4x² -17x + 60
10681062
f'(x) = 3x² -8x -17
10691063
"""
1070-
# polynomial_derivative([1, -4, -17, 60]) -> [3, -8, -17]
1064+
# polynomial_derivative([1, -4, -17, 60]) --> [3, -8, -17]
10711065
n = len(coefficients)
10721066
powers = reversed(range(1, n))
10731067
return list(map(operator.mul, coefficients, powers))
@@ -1169,6 +1163,12 @@ The following recipes have a more mathematical flavor:
11691163

11701164
>>> take(10, count())
11711165
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1166+
>>> # Verify that the input is consumed lazily
1167+
>>> it = iter('abcdef')
1168+
>>> take(3, it)
1169+
['a', 'b', 'c']
1170+
>>> list(it)
1171+
['d', 'e', 'f']
11721172

11731173
>>> list(prepend(1, [2, 3, 4]))
11741174
[1, 2, 3, 4]
@@ -1181,25 +1181,45 @@ The following recipes have a more mathematical flavor:
11811181

11821182
>>> list(tail(3, 'ABCDEFG'))
11831183
['E', 'F', 'G']
1184+
>>> # Verify the input is consumed greedily
1185+
>>> input_iterator = iter('ABCDEFG')
1186+
>>> output_iterator = tail(3, input_iterator)
1187+
>>> list(input_iterator)
1188+
[]
11841189

11851190
>>> it = iter(range(10))
11861191
>>> consume(it, 3)
1192+
>>> # Verify the input is consumed lazily
11871193
>>> next(it)
11881194
3
1195+
>>> # Verify the input is consumed completely
11891196
>>> consume(it)
11901197
>>> next(it, 'Done')
11911198
'Done'
11921199

11931200
>>> nth('abcde', 3)
11941201
'd'
1195-
11961202
>>> nth('abcde', 9) is None
11971203
True
1204+
>>> # Verify that the input is consumed lazily
1205+
>>> it = iter('abcde')
1206+
>>> nth(it, 2)
1207+
'c'
1208+
>>> list(it)
1209+
['d', 'e']
11981210

11991211
>>> [all_equal(s) for s in ('', 'A', 'AAAA', 'AAAB', 'AAABA')]
12001212
[True, True, True, False, False]
12011213
>>> [all_equal(s, key=str.casefold) for s in ('', 'A', 'AaAa', 'AAAB', 'AAABA')]
12021214
[True, True, True, False, False]
1215+
>>> # Verify that the input is consumed lazily and that only
1216+
>>> # one element of a second equivalence class is used to disprove
1217+
>>> # the assertion that all elements are equal.
1218+
>>> it = iter('aaabbbccc')
1219+
>>> all_equal(it)
1220+
False
1221+
>>> ''.join(it)
1222+
'bbccc'
12031223

12041224
>>> quantify(range(99), lambda x: x%2==0)
12051225
50
@@ -1222,6 +1242,11 @@ The following recipes have a more mathematical flavor:
12221242

12231243
>>> list(ncycles('abc', 3))
12241244
['a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c']
1245+
>>> # Verify greedy consumption of input iterator
1246+
>>> input_iterator = iter('abc')
1247+
>>> output_iterator = ncycles(input_iterator, 3)
1248+
>>> list(input_iterator)
1249+
[]
12251250

12261251
>>> sum_of_squares([10, 20, 30])
12271252
1400
@@ -1248,19 +1273,41 @@ The following recipes have a more mathematical flavor:
12481273

12491274
>>> list(transpose([(1, 2, 3), (11, 22, 33)]))
12501275
[(1, 11), (2, 22), (3, 33)]
1276+
>>> # Verify that the inputs are consumed lazily
1277+
>>> input1 = iter([1, 2, 3])
1278+
>>> input2 = iter([11, 22, 33])
1279+
>>> output_iterator = transpose([input1, input2])
1280+
>>> next(output_iterator)
1281+
(1, 11)
1282+
>>> list(zip(input1, input2))
1283+
[(2, 22), (3, 33)]
12511284

12521285
>>> list(matmul([(7, 5), (3, 5)], [[2, 5], [7, 9]]))
12531286
[(49, 80), (41, 60)]
12541287
>>> list(matmul([[2, 5], [7, 9], [3, 4]], [[7, 11, 5, 4, 9], [3, 5, 2, 6, 3]]))
12551288
[(29, 47, 20, 38, 33), (76, 122, 53, 82, 90), (33, 53, 23, 36, 39)]
12561289

1290+
>>> list(convolve([1, -1, -20], [1, -3])) == [1, -4, -17, 60]
1291+
True
12571292
>>> data = [20, 40, 24, 32, 20, 28, 16]
12581293
>>> list(convolve(data, [0.25, 0.25, 0.25, 0.25]))
12591294
[5.0, 15.0, 21.0, 29.0, 29.0, 26.0, 24.0, 16.0, 11.0, 4.0]
12601295
>>> list(convolve(data, [1, -1]))
12611296
[20, 20, -16, 8, -12, 8, -12, -16]
12621297
>>> list(convolve(data, [1, -2, 1]))
12631298
[20, 0, -36, 24, -20, 20, -20, -4, 16]
1299+
>>> # Verify signal is consumed lazily and the kernel greedily
1300+
>>> signal_iterator = iter([10, 20, 30, 40, 50])
1301+
>>> kernel_iterator = iter([1, 2, 3])
1302+
>>> output_iterator = convolve(signal_iterator, kernel_iterator)
1303+
>>> list(kernel_iterator)
1304+
[]
1305+
>>> next(output_iterator)
1306+
10
1307+
>>> next(output_iterator)
1308+
40
1309+
>>> list(signal_iterator)
1310+
[30, 40, 50]
12641311

12651312
>>> from fractions import Fraction
12661313
>>> from decimal import Decimal
@@ -1348,6 +1395,33 @@ The following recipes have a more mathematical flavor:
13481395
>>> # Test list input. Lists do not support None for the stop argument
13491396
>>> list(iter_index(list('AABCADEAF'), 'A'))
13501397
[0, 1, 4, 7]
1398+
>>> # Verify that input is consumed lazily
1399+
>>> input_iterator = iter('AABCADEAF')
1400+
>>> output_iterator = iter_index(input_iterator, 'A')
1401+
>>> next(output_iterator)
1402+
0
1403+
>>> next(output_iterator)
1404+
1
1405+
>>> next(output_iterator)
1406+
4
1407+
>>> ''.join(input_iterator)
1408+
'DEAF'
1409+
1410+
>>> # Verify that the target value can be a sequence.
1411+
>>> seq = [[10, 20], [30, 40], 30, 40, [30, 40], 50]
1412+
>>> target = [30, 40]
1413+
>>> list(iter_index(seq, target))
1414+
[1, 4]
1415+
1416+
>>> # Verify faithfulness to type specific index() method behaviors.
1417+
>>> # For example, bytes and str perform subsequence searches
1418+
>>> # that do not match the general behavior specified
1419+
>>> # in collections.abc.Sequence.index().
1420+
>>> seq = 'abracadabra'
1421+
>>> target = 'ab'
1422+
>>> list(iter_index(seq, target))
1423+
[0, 7]
1424+
13511425

13521426
>>> list(sieve(30))
13531427
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
@@ -1490,6 +1564,9 @@ The following recipes have a more mathematical flavor:
14901564

14911565
>>> list(roundrobin('abc', 'd', 'ef'))
14921566
['a', 'd', 'e', 'b', 'f', 'c']
1567+
>>> ranges = [range(5, 1000), range(4, 3000), range(0), range(3, 2000), range(2, 5000), range(1, 3500)]
1568+
>>> collections.Counter(roundrobin(ranges)) == collections.Counter(ranges)
1569+
True
14931570

14941571
>>> def is_odd(x):
14951572
... return x % 2 == 1
@@ -1499,6 +1576,17 @@ The following recipes have a more mathematical flavor:
14991576
[0, 2, 4, 6, 8]
15001577
>>> list(odds)
15011578
[1, 3, 5, 7, 9]
1579+
>>> # Verify that the input is consumed lazily
1580+
>>> input_iterator = iter(range(10))
1581+
>>> evens, odds = partition(is_odd, input_iterator)
1582+
>>> next(odds)
1583+
1
1584+
>>> next(odds)
1585+
3
1586+
>>> next(evens)
1587+
0
1588+
>>> list(input_iterator)
1589+
[4, 5, 6, 7, 8, 9]
15021590

15031591
>>> list(subslices('ABCD'))
15041592
['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
@@ -1518,13 +1606,27 @@ The following recipes have a more mathematical flavor:
15181606
['A', 'B', 'C', 'D']
15191607
>>> list(unique_everseen('ABBcCAD', str.casefold))
15201608
['A', 'B', 'c', 'D']
1609+
>>> # Verify that the input is consumed lazily
1610+
>>> input_iterator = iter('AAAABBBCCDAABBB')
1611+
>>> output_iterator = unique_everseen(input_iterator)
1612+
>>> next(output_iterator)
1613+
'A'
1614+
>>> ''.join(input_iterator)
1615+
'AAABBBCCDAABBB'
15211616

15221617
>>> list(unique_justseen('AAAABBBCCDAABBB'))
15231618
['A', 'B', 'C', 'D', 'A', 'B']
15241619
>>> list(unique_justseen('ABBCcAD', str.casefold))
15251620
['A', 'B', 'C', 'A', 'D']
15261621
>>> list(unique_justseen('ABBcCAD', str.casefold))
15271622
['A', 'B', 'c', 'A', 'D']
1623+
>>> # Verify that the input is consumed lazily
1624+
>>> input_iterator = iter('AAAABBBCCDAABBB')
1625+
>>> output_iterator = unique_justseen(input_iterator)
1626+
>>> next(output_iterator)
1627+
'A'
1628+
>>> ''.join(input_iterator)
1629+
'AAABBBCCDAABBB'
15281630

15291631
>>> d = dict(a=1, b=2, c=3)
15301632
>>> it = iter_except(d.popitem, KeyError)
@@ -1545,6 +1647,12 @@ The following recipes have a more mathematical flavor:
15451647

15461648
>>> first_true('ABC0DEF1', '9', str.isdigit)
15471649
'0'
1650+
>>> # Verify that inputs are consumed lazily
1651+
>>> it = iter('ABC0DEF1')
1652+
>>> first_true(it, predicate=str.isdigit)
1653+
'0'
1654+
>>> ''.join(it)
1655+
'DEF1'
15481656

15491657

15501658
.. testcode::

Doc/library/math.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ Special functions
592592

593593
The :func:`erf` function can be used to compute traditional statistical
594594
functions such as the `cumulative standard normal distribution
595-
<https://en.wikipedia.org/wiki/Normal_distribution#Cumulative_distribution_functions>`_::
595+
<https://en.wikipedia.org/wiki/Cumulative_distribution_function>`_::
596596

597597
def phi(x):
598598
'Cumulative distribution function for the standard normal distribution'

0 commit comments

Comments
 (0)