From 97689ec8da5f03f79592446d7d16cb76a8fa5af2 Mon Sep 17 00:00:00 2001 From: qexat <43090614+qexat@users.noreply.github.com> Date: Tue, 23 Apr 2024 21:21:17 +0000 Subject: [PATCH 1/2] chore: build docs --- docs/magic_list.html | 3640 +++++++++++++++++++++--------------------- docs/search.js | 4 +- 2 files changed, 1861 insertions(+), 1783 deletions(-) diff --git a/docs/magic_list.html b/docs/magic_list.html index 0dadb9d..97c4493 100644 --- a/docs/magic_list.html +++ b/docs/magic_list.html @@ -167,7 +167,7 @@
They can be imported as following:
@@ -186,19 +186,20 @@25class list(collections.UserList[_T]): +@@ -1159,9 +1197,10 @@25class list(collections.UserList[_T]): # noqa: A001, N801 26 """ 27 Mutable homogeneous sequence. 28 Drop-in replacement for the built-in `list` type. @@ -234,900 +235,937 @@42 """ 43 44 if not self: - 45 raise TypeError("empty list has no head") - 46 - 47 return self[0] - 48 - 49 @property - 50 def tail(self) -> typing_extensions.Self: - 51 """ - 52 List without its first item. - 53 - 54 .. warning:: The list must be non-empty. - 55 - 56 >>> L[3, 5, 2].tail - 57 [5, 2] - 58 >>> list().tail - 59 *- TypeError: empty list has no tail -* - 60 """ - 61 - 62 if not self: - 63 raise TypeError("empty list has no tail") - 64 - 65 return self.__class__(self[1:]) + 45 msg = "empty list has no head" + 46 raise TypeError(msg) + 47 + 48 return self[0] + 49 + 50 @property + 51 def tail(self) -> typing_extensions.Self: + 52 """ + 53 List without its first item. + 54 + 55 .. warning:: The list must be non-empty. + 56 + 57 >>> L[3, 5, 2].tail + 58 [5, 2] + 59 >>> list().tail + 60 *- TypeError: empty list has no tail -* + 61 """ + 62 + 63 if not self: + 64 msg = "empty list has no tail" + 65 raise TypeError(msg) 66 - 67 @property - 68 def init(self) -> typing_extensions.Self: - 69 """ - 70 List without its last item. - 71 - 72 .. warning:: The list must be non-empty. + 67 return self.__class__(self[1:]) + 68 + 69 @property + 70 def init(self) -> typing_extensions.Self: + 71 """ + 72 List without its last item. 73 - 74 >>> L[3, 5, 2].init - 75 [3, 5] - 76 >>> list().init - 77 *- TypeError: empty list has no init -* - 78 """ - 79 - 80 if not self: - 81 raise TypeError("empty list has no init") - 82 - 83 return self.__class__(self[:-1]) - 84 - 85 @property - 86 def last(self) -> _T: - 87 """ - 88 Last item of the list. - 89 - 90 .. warning:: The list must be non-empty. - 91 - 92 >>> L[3, 5, 2].last - 93 2 - 94 >>> list().last - 95 *- TypeError: empty list has no last -* - 96 """ - 97 - 98 if not self: - 99 raise TypeError("empty list has no last") + 74 .. warning:: The list must be non-empty. + 75 + 76 >>> L[3, 5, 2].init + 77 [3, 5] + 78 >>> list().init + 79 *- TypeError: empty list has no init -* + 80 """ + 81 + 82 if not self: + 83 msg = "empty list has no init" + 84 raise TypeError(msg) + 85 + 86 return self.__class__(self[:-1]) + 87 + 88 @property + 89 def last(self) -> _T: + 90 """ + 91 Last item of the list. + 92 + 93 .. warning:: The list must be non-empty. + 94 + 95 >>> L[3, 5, 2].last + 96 2 + 97 >>> list().last + 98 *- TypeError: empty list has no last -* + 99 """ 100 -101 return self[-1] -102 -103 def prepend(self, item: _T) -> None: -104 """ -105 Add an item at the beginning of the list. +101 if not self: +102 msg = "empty list has no last" +103 raise TypeError(msg) +104 +105 return self[-1] 106 -107 >>> l = L[3, 5, 2] -108 >>> l.prepend(-2) -109 >>> print(l) -110 [-2, 3, 5, 2] -111 """ -112 -113 self.insert(0, item) -114 -115 def reversed(self) -> typing_extensions.Self: -116 """ -117 Return a reversed version of the list. +107 def prepend(self, item: _T) -> None: +108 """ +109 Add an item at the beginning of the list. +110 +111 >>> l = L[3, 5, 2] +112 >>> l.prepend(-2) +113 >>> print(l) +114 [-2, 3, 5, 2] +115 """ +116 +117 self.insert(0, item) 118 -119 >>> L[1, 2, 3].reversed() -120 [3, 2, 1] -121 """ +119 def reversed(self) -> typing_extensions.Self: +120 """ +121 Return a reversed version of the list. 122 -123 # we avoid constructing a whole `reversed` object -124 return self.__class__(self.__reversed__()) -125 -126 def sorted( -127 self, -128 *, -129 key: collections.abc.Callable[[_T], _typeshed.SupportsRichComparison] -130 | None = None, -131 reverse: bool = False, -132 ) -> typing_extensions.Self: -133 """ -134 Return a sorted version of the list. -135 -136 >>> L[3, 5, 2].sorted() -137 [2, 3, 5] -138 >>> list("gala").sorted(key=ord) -139 ["a", "a", "g", "l"] -140 """ -141 -142 return self.__class__(sorted(self, key=key, reverse=reverse)) # type: ignore -143 -144 def shuffled(self) -> typing_extensions.Self: -145 """ -146 Return a shuffled version of the list. +123 >>> L[1, 2, 3].reversed() +124 [3, 2, 1] +125 """ +126 +127 # we avoid constructing a whole `reversed` object +128 return self.__class__(self.__reversed__()) +129 +130 def sorted( +131 self, +132 *, +133 key: collections.abc.Callable[[_T], _typeshed.SupportsRichComparison] +134 | None = None, +135 reverse: bool = False, +136 ) -> typing_extensions.Self: +137 """ +138 Return a sorted version of the list. +139 +140 >>> L[3, 5, 2].sorted() +141 [2, 3, 5] +142 >>> list("gala").sorted(key=ord) +143 ["a", "a", "g", "l"] +144 """ +145 +146 return self.__class__(sorted(self, key=key, reverse=reverse)) # pyright: ignore[reportCallIssue, reportArgumentType] 147 -148 >>> L[3, 5, 2].shuffled() -149 [5, 2, 3] -150 >>> L[3, 5, 2].shuffled() -151 [2, 5, 3] -152 >>> list().shuffled() -153 [] -154 """ -155 -156 result = self.copy() -157 random.shuffle(result) -158 -159 return result -160 -161 def map(self, function: collections.abc.Callable[[_T], _U]) -> list[_U]: -162 """ -163 Apply `function` on each item of the list. +148 def shuffled(self) -> typing_extensions.Self: +149 """ +150 Return a shuffled version of the list. +151 +152 >>> L[3, 5, 2].shuffled() +153 [5, 2, 3] +154 >>> L[3, 5, 2].shuffled() +155 [2, 5, 3] +156 >>> list().shuffled() +157 [] +158 """ +159 +160 result = self.copy() +161 random.shuffle(result) +162 +163 return result 164 -165 >>> L[3, 5, 2].map(str) -166 ["3", "5", "2"] -167 >>> L[3, 5, 2].map(lambda n: n * 2) -168 [6, 10, 4] -169 >>> list().map(lambda n: n * 20) -170 [] -171 """ -172 -173 # subclasses' `map` return type is also marked as `list` because we -174 # cannot make the container generic -- this requires Higher-Kinded -175 # Types, which Python does not support (yet? hopefully!) +165 def map(self, function: collections.abc.Callable[[_T], _U]) -> list[_U]: +166 """ +167 Apply `function` on each item of the list. +168 +169 >>> L[3, 5, 2].map(str) +170 ["3", "5", "2"] +171 >>> L[3, 5, 2].map(lambda n: n * 2) +172 [6, 10, 4] +173 >>> list().map(lambda n: n * 20) +174 [] +175 """ 176 -177 return typing.cast(list[_U], self.__class__(map(function, self))) -178 -179 def rotate(self, n: int = 1) -> typing_extensions.Self: -180 """ -181 Shift the list `n` times to the right. The items that overflow get prepended. +177 # subclasses' `map` return type is also marked as `list` because we +178 # cannot make the container generic -- this requires Higher-Kinded +179 # Types, which Python does not support (yet? hopefully!) +180 +181 return typing.cast(list[_U], self.__class__(map(function, self))) 182 -183 If `n` is negative, the shift goes to the left. -184 -185 .. warning:: The list must be non-empty. +183 def rotate(self, n: int = 1) -> typing_extensions.Self: +184 """ +185 Shift the list `n` times to the right. The items that overflow get prepended. 186 -187 >>> L[3, 5, 2].rotate() -188 [2, 3, 5] -189 >>> L[3, 5, 2].rotate(2) -190 [5, 2, 3] -191 >>> L[3, 5, 2].rotate(-1) -192 [5, 2, 3] -193 >>> list().rotate() -194 *- TypeError: empty list cannot be rotated -* -195 """ -196 -197 if not self: -198 raise TypeError("empty list cannot be rotated") -199 -200 if n == 0: -201 return self -202 -203 returned_list = self.copy() +187 If `n` is negative, the shift goes to the left. +188 +189 .. warning:: The list must be non-empty. +190 +191 >>> L[3, 5, 2].rotate() +192 [2, 3, 5] +193 >>> L[3, 5, 2].rotate(2) +194 [5, 2, 3] +195 >>> L[3, 5, 2].rotate(-1) +196 [5, 2, 3] +197 >>> list().rotate() +198 *- TypeError: empty list cannot be rotated -* +199 """ +200 +201 if not self: +202 msg = "empty list cannot be rotated" +203 raise TypeError(msg) 204 -205 if n > 0: -206 xpend_method = returned_list.prepend -207 popped_index = -1 -208 else: -209 xpend_method = returned_list.append -210 popped_index = 0 -211 -212 for _ in range(abs(n)): -213 xpend_method(returned_list.pop(popped_index)) -214 -215 return returned_list +205 if n == 0: +206 return self +207 +208 returned_list = self.copy() +209 +210 if n > 0: +211 xpend_method = returned_list.prepend +212 popped_index = -1 +213 else: +214 xpend_method = returned_list.append +215 popped_index = 0 216 -217 def filter( -218 self, -219 function: collections.abc.Callable[[_T], bool], -220 ) -> typing_extensions.Self: -221 """ -222 Discard each item `i` of the list if `function(i)` is `False`. -223 -224 >>> L[3, 5, 2].filter(lambda n: n % 2 == 1) -225 [3, 5] -226 >>> L["hello", "hola", "bonjour"].filter(lambda s: "l" in s) -227 ["hello", "hola"] -228 >>> list().filter(lambda n: n > 0) -229 [] -230 """ -231 -232 return self.__class__(filter(function, self)) -233 -234 def mask( -235 self, -236 mask_seq: collections.abc.Sequence[bool], -237 ) -> typing_extensions.Self: -238 """ -239 Keep every item at index `i` of the list if the corresponding -240 item at index `i` of the mask sequence is `True` ; else, discard -241 it. Return the filtered list. -242 -243 .. warning:: The mask sequence must be of the same length as the list. -244 -245 >>> L[3, 5, 2].mask([True, False, True]) -246 [3, 2] -247 >>> list().mask([]) -248 [] -249 >>> L[3, 5, 2].mask([True, False]) -250 *- TypeError: mask length must be the same as the list -* -251 """ -252 -253 if len(self) != len(mask_seq): -254 raise TypeError("mask length must be the same as the list") -255 -256 return self.__class__(item for item, bit in zip(self, mask_seq) if bit) +217 for _ in range(abs(n)): +218 xpend_method(returned_list.pop(popped_index)) +219 +220 return returned_list +221 +222 def filter( +223 self, +224 function: collections.abc.Callable[[_T], bool], +225 ) -> typing_extensions.Self: +226 """ +227 Discard each item `i` of the list if `function(i)` is `False`. +228 +229 >>> L[3, 5, 2].filter(lambda n: n % 2 == 1) +230 [3, 5] +231 >>> L["hello", "hola", "bonjour"].filter(lambda s: "l" in s) +232 ["hello", "hola"] +233 >>> list().filter(lambda n: n > 0) +234 [] +235 """ +236 +237 return self.__class__(filter(function, self)) +238 +239 def mask( +240 self, +241 mask_seq: collections.abc.Sequence[bool], +242 ) -> typing_extensions.Self: +243 """ +244 Keep every item at index `i` of the list if the corresponding +245 item at index `i` of the mask sequence is `True` ; else, discard +246 it. Return the filtered list. +247 +248 .. warning:: The mask sequence must be of the same length as the list. +249 +250 >>> L[3, 5, 2].mask([True, False, True]) +251 [3, 2] +252 >>> list().mask([]) +253 [] +254 >>> L[3, 5, 2].mask([True, False]) +255 *- TypeError: mask length must be the same as the list -* +256 """ 257 -258 def deduplicate(self) -> typing_extensions.Self: -259 """ -260 Remove duplicate elements from left to right (and keep original ones). -261 Return the deduplicated list. -262 -263 >>> L[3, 0, 0, 1, 18].deduplicate() -264 [3, 0, 1, 18] -265 >>> L["hello", "hello", "world", "world"].deduplicate() -266 ["hello", "world"] -267 >>> list().deduplicate() -268 [] -269 """ -270 -271 returned_list: typing_extensions.Self = self.__class__() -272 -273 for elem in self: -274 if elem not in returned_list: -275 returned_list.append(elem) +258 if len(self) != len(mask_seq): +259 msg = "mask length must be the same as the list" +260 raise TypeError(msg) +261 +262 return self.__class__(item for item, bit in zip(self, mask_seq) if bit) +263 +264 def deduplicate(self) -> typing_extensions.Self: +265 """ +266 Remove duplicate elements from left to right (and keep original ones). +267 Return the deduplicated list. +268 +269 >>> L[3, 0, 0, 1, 18].deduplicate() +270 [3, 0, 1, 18] +271 >>> L["hello", "hello", "world", "world"].deduplicate() +272 ["hello", "world"] +273 >>> list().deduplicate() +274 [] +275 """ 276 -277 return returned_list +277 returned_list: typing_extensions.Self = self.__class__() 278 -279 def reduce(self, function: collections.abc.Callable[[_T, _T], _T]) -> _T: -280 """ -281 "Insert" an operator (called a reducing function) between each item -282 from left to right and return the result. -283 -284 The first item of the list is used as the leftmost value ; -285 therefore, if the list is empty, it will raise an exception. -286 -287 .. warning:: The list must be non-empty. -288 -289 >>> L[3, 5, 2].reduce(operator.add) # (3 + 5) + 2 -290 10 -291 >>> list().reduce(operator.mul) -292 *- TypeError: the list to reduce cannot be empty -* -293 """ +279 for elem in self: +280 if elem not in returned_list: +281 returned_list.append(elem) +282 +283 return returned_list +284 +285 def reduce(self, function: collections.abc.Callable[[_T, _T], _T]) -> _T: +286 """ +287 "Insert" an operator (called a reducing function) between each item +288 from left to right and return the result. +289 +290 The first item of the list is used as the leftmost value ; +291 therefore, if the list is empty, it will raise an exception. +292 +293 .. warning:: The list must be non-empty. 294 -295 if not self: -296 raise TypeError("the list to reduce cannot be empty") -297 -298 return functools.reduce(function, self) -299 -300 def reduce_right( -301 self, -302 function: collections.abc.Callable[[_T, _T], _T], -303 ) -> _T: -304 """ -305 "Insert" an operator (called a reducing function) between each item -306 from right to left and return the result. -307 -308 The last item of the list is used as the leftmost value ; -309 therefore, if the list is empty, it will raise an exception. -310 -311 .. warning:: The list must be non-empty. -312 -313 >>> L[3, 5, 2].reduce_right(operator.add) # 3 + (5 + 2) -314 10 -315 >>> L[3, 5, 2].reduce_right(operator.sub) # 3 - (5 - 2) -316 0 -317 >>> list().reduce_right(operator.add) -318 *- TypeError: the list to reduce cannot be empty -* -319 """ -320 -321 if not self: -322 raise TypeError("the list to reduce cannot be empty") -323 -324 return functools.reduce(lambda a, b: function(b, a), self.reversed()) -325 -326 def fold( -327 self, -328 function: collections.abc.Callable[[_T, _T], _T], -329 initial_value: _T, -330 ) -> _T: -331 """ -332 "Insert" an operator (called a reducing function) between each item -333 from left to right and return the result. -334 -335 The `initial_value` is used as the leftmost value, and is the returned -336 value if the list is empty. -337 -338 >>> L[3, 5, 2].fold(operator.add, -3) # ((-3 + 3) + 5) + 2 -339 7 -340 >>> list().fold(operator.mul, 0) -341 0 -342 """ -343 -344 return functools.reduce(function, self, initial_value) +295 >>> L[3, 5, 2].reduce(operator.add) # (3 + 5) + 2 +296 10 +297 >>> list().reduce(operator.mul) +298 *- TypeError: the list to reduce cannot be empty -* +299 """ +300 +301 if not self: +302 msg = "the list to reduce cannot be empty" +303 raise TypeError(msg) +304 +305 return functools.reduce(function, self) +306 +307 def reduce_right( +308 self, +309 function: collections.abc.Callable[[_T, _T], _T], +310 ) -> _T: +311 """ +312 "Insert" an operator (called a reducing function) between each item +313 from right to left and return the result. +314 +315 The last item of the list is used as the leftmost value ; +316 therefore, if the list is empty, it will raise an exception. +317 +318 .. warning:: The list must be non-empty. +319 +320 >>> L[3, 5, 2].reduce_right(operator.add) # 3 + (5 + 2) +321 10 +322 >>> L[3, 5, 2].reduce_right(operator.sub) # 3 - (5 - 2) +323 0 +324 >>> list().reduce_right(operator.add) +325 *- TypeError: the list to reduce cannot be empty -* +326 """ +327 +328 if not self: +329 msg = "the list to reduce cannot be empty" +330 raise TypeError(msg) +331 +332 return functools.reduce(lambda a, b: function(b, a), self.reversed()) +333 +334 def fold( +335 self, +336 function: collections.abc.Callable[[_T, _T], _T], +337 initial_value: _T, +338 ) -> _T: +339 """ +340 "Insert" an operator (called a reducing function) between each item +341 from left to right and return the result. +342 +343 The `initial_value` is used as the leftmost value, and is the returned +344 value if the list is empty. 345 -346 def fold_right( -347 self, -348 function: collections.abc.Callable[[_T, _T], _T], -349 initial_value: _T, -350 ) -> _T: -351 """ -352 "Insert" an operator (called a reducing function) between each item -353 from right to left and return the result. -354 -355 The `initial_value` is used as the leftmost value, and is the -356 returned value if the list is empty. -357 -358 >>> L[3, 5, 2].fold_right(operator.sub, -3) # -3 - (3 - (5 - 2)) -359 0 -360 >>> list().fold_right(operator.mul, 0) -361 0 -362 """ -363 -364 return functools.reduce( -365 lambda a, b: function(b, a), -366 self.reversed(), -367 initial_value, -368 ) -369 -370 def scan( -371 self, -372 function: collections.abc.Callable[[_T, _T], _T], -373 initial_value: _T, -374 ) -> typing_extensions.Self: -375 """ -376 "Insert" an operator (called a reducing function) between each item -377 from left to right and return the intermediate values followed by the -378 result. -379 -380 The `initial_value` is used as the leftmost value, and is the only -381 value of the returned list if the original list is empty. -382 -383 >>> L[3, 5, 2].scan(operator.add, 0) # [0, (0 + 3), (0 + 3 + 5), (0 + 3 + 5 + 2)] -384 [0, 3, 8, 10] -385 >>> list().scan(operator.add, 0) -386 [0] -387 """ -388 -389 result_tail = self.__class__() +346 >>> L[3, 5, 2].fold(operator.add, -3) # ((-3 + 3) + 5) + 2 +347 7 +348 >>> list().fold(operator.mul, 0) +349 0 +350 """ +351 +352 return functools.reduce(function, self, initial_value) +353 +354 def fold_right( +355 self, +356 function: collections.abc.Callable[[_T, _T], _T], +357 initial_value: _T, +358 ) -> _T: +359 """ +360 "Insert" an operator (called a reducing function) between each item +361 from right to left and return the result. +362 +363 The `initial_value` is used as the leftmost value, and is the +364 returned value if the list is empty. +365 +366 >>> L[3, 5, 2].fold_right(operator.sub, -3) # -3 - (3 - (5 - 2)) +367 0 +368 >>> list().fold_right(operator.mul, 0) +369 0 +370 """ +371 +372 return functools.reduce( +373 lambda a, b: function(b, a), +374 self.reversed(), +375 initial_value, +376 ) +377 +378 def scan( +379 self, +380 function: collections.abc.Callable[[_T, _T], _T], +381 initial_value: _T, +382 ) -> typing_extensions.Self: +383 """ +384 "Insert" an operator (called a reducing function) between each item +385 from left to right and return the intermediate values followed by the +386 result. +387 +388 The `initial_value` is used as the leftmost value, and is the only +389 value of the returned list if the original list is empty. 390 -391 if self: -392 head, *tail = self -393 result_tail.extend( -394 self.__class__(tail).scan( -395 function, -396 function(initial_value, head), -397 ), -398 ) +391 >>> # [0, (0 + 3), (0 + 3 + 5), (0 + 3 + 5 + 2)] +392 >>> L[3, 5, 2].scan(operator.add, 0) +393 [0, 3, 8, 10] +394 >>> list().scan(operator.add, 0) +395 [0] +396 """ +397 +398 result_tail = self.__class__() 399 -400 return self.__class__([initial_value]) + result_tail -401 -402 def scan_right( -403 self, -404 function: collections.abc.Callable[[_T, _T], _T], -405 initial_value: _T, -406 ) -> typing_extensions.Self: -407 """ -408 "Insert" an operator (called a reducing function) between each item -409 from right to left and return the intermediate values followed by the -410 result. -411 -412 The `initial_value` is used as the leftmost value, and is the only -413 value of the returned list if the original list is empty. -414 -415 >>> L[3, 5, 2].scan_right(operator.add, 0) # [0, (2 + 0), (5 + 2 + 0), (3 + 5 + 2 + 0)] -416 [0, 2, 7, 10] -417 >>> list().scan_right(operator.add, 0) -418 [0] -419 """ +400 if self: +401 head, *tail = self +402 result_tail.extend( +403 self.__class__(tail).scan( +404 function, +405 function(initial_value, head), +406 ), +407 ) +408 +409 return self.__class__([initial_value]) + result_tail +410 +411 def scan_right( +412 self, +413 function: collections.abc.Callable[[_T, _T], _T], +414 initial_value: _T, +415 ) -> typing_extensions.Self: +416 """ +417 "Insert" an operator (called a reducing function) between each item +418 from right to left and return the intermediate values followed by the +419 result. 420 -421 return self.reversed().scan(lambda a, b: function(b, a), initial_value) -422 -423 def merge( -424 self, -425 function: collections.abc.Callable[[_T, _U], _V], -426 other: collections.abc.Sequence[_U], -427 ) -> list[_V]: -428 """ -429 Build a new list from the result of each `function(s_i, o_i)` where -430 `s_i` and `o_i` are the items at index `i` of `self` and `other` -431 respectively. +421 The `initial_value` is used as the leftmost value, and is the only +422 value of the returned list if the original list is empty. +423 +424 >>> # [0, (2 + 0), (5 + 2 + 0), (3 + 5 + 2 + 0)] +425 >>> L[3, 5, 2].scan_right(operator.add, 0) +426 [0, 2, 7, 10] +427 >>> list().scan_right(operator.add, 0) +428 [0] +429 """ +430 +431 return self.reversed().scan(lambda a, b: function(b, a), initial_value) 432 -433 .. warning:: The list and the sequence must have the same length. -434 -435 >>> L[3, 5, 2].merge(operator.add, [-1, 4, -9]) -436 [2, 9, -7] -437 >>> list().merge(operator.sub, []) -438 [] -439 >>> L[3, 5, 2].merge(operator.add, [6]) -440 *- TypeError: the length of the two sequences must be equal -* -441 """ +433 def merge( +434 self, +435 function: collections.abc.Callable[[_T, _U], _V], +436 other: collections.abc.Sequence[_U], +437 ) -> list[_V]: +438 """ +439 Build a new list from the result of each `function(s_i, o_i)` where +440 `s_i` and `o_i` are the items at index `i` of `self` and `other` +441 respectively. 442 -443 if len(self) != len(other): -444 raise TypeError("the length of the two sequences must be equal") -445 -446 return typing.cast( -447 list[_V], -448 self.__class__(function(a, b) for a, b in zip(self, other)), -449 ) -450 -451 def flatten(self, *, _base: list[typing.Any] | None = None) -> list[typing.Any]: -452 """ -453 Flatten the contents to a 1-dimension list. If the list contains -454 itself, it cannot be flattened and a `ValueError` is raised. -455 -456 .. warning:: The list cannot contain recursive elements. -457 -458 >>> L[[3, 5, 2], [8, 4, 1], [7, 6, 9]].flatten() -459 [3, 5, 2, 8, 4, 1, 7, 6, 9] -460 >>> list().flatten() -461 [] -462 >>> l = list() -463 >>> l.append(l) -464 >>> l.flatten() -465 *- ValueError: cannot flatten list because it contains recursive elements -* -466 """ -467 -468 err = ValueError("cannot flatten list because it contains recursive elements") -469 -470 result: list[typing.Any] = list() -471 -472 for item in self: -473 if item is self or item is _base: -474 raise err -475 -476 base = self if _base is None else _base -477 -478 if isinstance(item, list): -479 result.extend(item.flatten(_base=base)) -480 elif isinstance(item, collections.abc.Iterable): -481 try: -482 result.extend( -483 list( -484 typing.cast(collections.abc.Iterable[typing.Any], item), -485 ).flatten(_base=base), -486 ) -487 except RecursionError: -488 # a bit dirty but I can't think of any other solution 😅 -489 raise err from None -490 else: -491 result.append(item) -492 -493 return result -494 -495 def sum(self) -> _T: -496 """ -497 Return the sum of the list. The elements must support addition, -498 otherwise an exception is raised. -499 -500 .. warning:: The list must contain values that support the `+` operator, and be non-empty. -501 -502 >>> L[3, 5, 2].sum() -503 10 -504 >>> L["hello", "world"].sum() -505 "helloworld" -506 >>> list().sum() -507 *- TypeError: cannot perform summation on an empty list -* -508 """ -509 -510 if not self: -511 raise TypeError("cannot perform summation on an empty list") -512 -513 return self.reduce(operator.add) -514 -515 def mean(self: list[int] | list[float] | list[complex]) -> float | complex: -516 """ -517 Return the mean of the list. The elements must be numbers. -518 -519 .. warning:: The list must contain numbers and be non-empty. -520 -521 >>> L[3, 5, 2].mean() -522 3.3333333333333335 -523 >>> L["hello", "world"].mean() -524 *- TypeError: cannot calculate mean of list of str -* -525 >>> list().mean() -526 *- TypeError: cannot calculate mean of empty list -* -527 """ -528 -529 if not self: -530 raise TypeError("cannot calculate mean of empty list") +443 .. warning:: The list and the sequence must have the same length. +444 +445 >>> L[3, 5, 2].merge(operator.add, [-1, 4, -9]) +446 [2, 9, -7] +447 >>> list().merge(operator.sub, []) +448 [] +449 >>> L[3, 5, 2].merge(operator.add, [6]) +450 *- TypeError: the length of the two sequences must be equal -* +451 """ +452 +453 if len(self) != len(other): +454 msg = "the length of the two sequences must be equal" +455 raise TypeError(msg) +456 +457 return typing.cast( +458 list[_V], +459 self.__class__(function(a, b) for a, b in zip(self, other)), +460 ) +461 +462 def flatten(self, *, _base: list[typing.Any] | None = None) -> list[typing.Any]: +463 """ +464 Flatten the contents to a 1-dimension list. If the list contains +465 itself, it cannot be flattened and a `ValueError` is raised. +466 +467 .. warning:: The list cannot contain recursive elements. +468 +469 >>> L[[3, 5, 2], [8, 4, 1], [7, 6, 9]].flatten() +470 [3, 5, 2, 8, 4, 1, 7, 6, 9] +471 >>> list().flatten() +472 [] +473 >>> l = list() +474 >>> l.append(l) +475 >>> l.flatten() +476 *- ValueError: cannot flatten list because it contains recursive elements -* +477 """ +478 +479 err = ValueError("cannot flatten list because it contains recursive elements") +480 +481 result: list[typing.Any] = list() +482 +483 for item in self: +484 if item is self or item is _base: +485 raise err +486 +487 base = self if _base is None else _base +488 +489 if isinstance(item, list): +490 result.extend(item.flatten(_base=base)) +491 elif isinstance(item, collections.abc.Iterable): +492 try: +493 result.extend( +494 list( +495 typing.cast(collections.abc.Iterable[typing.Any], item), +496 ).flatten(_base=base), +497 ) +498 except RecursionError: +499 # a bit dirty but I can't think of any other solution 😅 +500 raise err from None +501 else: +502 result.append(item) +503 +504 return result +505 +506 def sum(self) -> _T: +507 """ +508 Return the sum of the list. The elements must support addition, +509 otherwise an exception is raised. +510 +511 .. warning:: The list must contain values that support the `+` \ +512 operator, and be non-empty. +513 +514 >>> L[3, 5, 2].sum() +515 10 +516 >>> L["hello", "world"].sum() +517 "helloworld" +518 >>> list().sum() +519 *- TypeError: cannot perform summation on an empty list -* +520 """ +521 +522 if not self: +523 msg = "cannot perform summation on an empty list" +524 raise TypeError(msg) +525 +526 return self.reduce(operator.add) +527 +528 def mean(self: list[int] | list[float] | list[complex]) -> float | complex: +529 """ +530 Return the mean of the list. The elements must be numbers. 531 -532 if not hasattr(self[0], "__truediv__"): -533 raise TypeError( -534 f"cannot calculate mean of list of {self[0].__class__.__name__}", -535 ) -536 -537 return sum(self) / len(self) -538 -539 def min(self: list[int] | list[float]) -> int | float: -540 """ -541 Return the minimum value of the list. -542 -543 .. warning:: The list must be non-empty and contain numbers. -544 -545 >>> L[3, 5, 2].min() -546 2 -547 >>> L["hello", "world"].min() -548 *- TypeError: list of str has no minimum -* -549 >>> list().min() -550 *- TypeError: empty list has no minimum -* -551 """ -552 -553 if not self: -554 raise TypeError("empty list has no minimum") -555 -556 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] -557 raise TypeError(f"list of {type(self.head).__name__} has no minimum") -558 -559 return min(self) -560 -561 def max(self: list[int] | list[float]) -> int | float: -562 """ -563 Return the maximum value of the list. -564 -565 .. warning:: The list must be non-empty and contain numbers. -566 -567 >>> L[3, 5, 2].max() -568 2 -569 >>> L["hello", "world"].max() -570 *- TypeError: list of str has no maximum -* -571 >>> list().max() -572 *- TypeError: empty list has no maximum -* -573 """ -574 -575 if not self: -576 raise TypeError("empty list has no maximum") +532 .. warning:: The list must contain numbers and be non-empty. +533 +534 >>> L[3, 5, 2].mean() +535 3.3333333333333335 +536 >>> L["hello", "world"].mean() +537 *- TypeError: cannot calculate mean of list of str -* +538 >>> list().mean() +539 *- TypeError: cannot calculate mean of empty list -* +540 """ +541 +542 if not self: +543 msg = "cannot calculate mean of empty list" +544 raise TypeError(msg) +545 +546 if not hasattr(self[0], "__truediv__"): +547 msg = f"cannot calculate mean of list of {self[0].__class__.__name__}" +548 raise TypeError( +549 msg, +550 ) +551 +552 return sum(self) / len(self) +553 +554 def min(self: list[int] | list[float]) -> int | float: +555 """ +556 Return the minimum value of the list. +557 +558 .. warning:: The list must be non-empty and contain numbers. +559 +560 >>> L[3, 5, 2].min() +561 2 +562 >>> L["hello", "world"].min() +563 *- TypeError: list of str has no minimum -* +564 >>> list().min() +565 *- TypeError: empty list has no minimum -* +566 """ +567 +568 if not self: +569 msg = "empty list has no minimum" +570 raise TypeError(msg) +571 +572 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] +573 msg = f"list of {type(self.head).__name__} has no minimum" +574 raise TypeError(msg) +575 +576 return min(self) 577 -578 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] -579 raise TypeError(f"list of {type(self.head).__name__} has no maximum") -580 -581 return max(self) -582 -583 def fill_left( -584 self, -585 filler: _T | collections.abc.Callable[[list[_T]], _T], -586 n: int, -587 ) -> typing_extensions.Self: -588 """ -589 Fill on the left the list with `filler` and return the result. -590 -591 If `filler` is a function, it takes the current list (at the current -592 filling iteration) and produces a new value to be appended. -593 -594 .. warning:: `n` must be non-negative. +578 def max(self: list[int] | list[float]) -> int | float: +579 """ +580 Return the maximum value of the list. +581 +582 .. warning:: The list must be non-empty and contain numbers. +583 +584 >>> L[3, 5, 2].max() +585 2 +586 >>> L["hello", "world"].max() +587 *- TypeError: list of str has no maximum -* +588 >>> list().max() +589 *- TypeError: empty list has no maximum -* +590 """ +591 +592 if not self: +593 msg = "empty list has no maximum" +594 raise TypeError(msg) 595 -596 >>> L[3, 5, 2].fill_left(0, 5) -597 [0, 0, 0, 0, 0, 3, 5, 2] -598 >>> L[3, 5, 2].fill_left(sum, 3) -599 [40, 20, 10, 3, 5, 2] -600 >>> list().fill_left(1, 10) -601 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] -602 >>> L[3, 5, 2].fill_left(0, -1) -603 *- ValueError: the number of times to fill cannot be negative -* -604 """ -605 -606 if n < 0: -607 raise ValueError("the number of times to fill cannot be negative") -608 -609 returned_list = self.copy() -610 -611 for _ in range(n): -612 returned_list.prepend(filler(returned_list) if callable(filler) else filler) -613 -614 return returned_list -615 -616 def fill_right( -617 self, -618 filler: _T | collections.abc.Callable[[list[_T]], _T], -619 n: int, -620 ) -> typing_extensions.Self: -621 """ -622 Fill on the right the list with `filler` and return the result. -623 -624 If `filler` is a function, it takes the current list (at the current -625 filling iteration) and produces a new value to be appended. -626 -627 .. warning:: `n` must be non-negative. +596 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] +597 msg = f"list of {type(self.head).__name__} has no maximum" +598 raise TypeError(msg) +599 +600 return max(self) +601 +602 def fill_left( +603 self, +604 filler: _T | collections.abc.Callable[[list[_T]], _T], +605 n: int, +606 ) -> typing_extensions.Self: +607 """ +608 Fill on the left the list with `filler` and return the result. +609 +610 If `filler` is a function, it takes the current list (at the current +611 filling iteration) and produces a new value to be appended. +612 +613 .. warning:: `n` must be non-negative. +614 +615 >>> L[3, 5, 2].fill_left(0, 5) +616 [0, 0, 0, 0, 0, 3, 5, 2] +617 >>> L[3, 5, 2].fill_left(sum, 3) +618 [40, 20, 10, 3, 5, 2] +619 >>> list().fill_left(1, 10) +620 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +621 >>> L[3, 5, 2].fill_left(0, -1) +622 *- ValueError: the number of times to fill cannot be negative -* +623 """ +624 +625 if n < 0: +626 msg = "the number of times to fill cannot be negative" +627 raise ValueError(msg) 628 -629 >>> L[3, 5, 2].fill_right(0, 5) -630 [3, 5, 2, 0, 0, 0, 0, 0] -631 >>> L[3, 5, 2].fill_right(sum, 3) -632 [3, 5, 2, 10, 20, 40] -633 >>> list().fill_right(1, 10) -634 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] -635 >>> L[3, 5, 2].fill_right(0, -1) -636 *- ValueError: the number of times to fill cannot be negative -* -637 """ -638 -639 if n < 0: -640 raise ValueError("the number of times to fill cannot be negative") -641 -642 returned_list = self.copy() +629 returned_list = self.copy() +630 +631 for _ in range(n): +632 returned_list.prepend(filler(returned_list) if callable(filler) else filler) +633 +634 return returned_list +635 +636 def fill_right( +637 self, +638 filler: _T | collections.abc.Callable[[list[_T]], _T], +639 n: int, +640 ) -> typing_extensions.Self: +641 """ +642 Fill on the right the list with `filler` and return the result. 643 -644 for _ in range(n): -645 returned_list.append(filler(returned_list) if callable(filler) else filler) +644 If `filler` is a function, it takes the current list (at the current +645 filling iteration) and produces a new value to be appended. 646 -647 return returned_list +647 .. warning:: `n` must be non-negative. 648 -649 def interleave( -650 self, -651 filler: _T | collections.abc.Callable[[_T, _T], _T], -652 ) -> typing_extensions.Self: -653 """ -654 Fill in-between the items with `filler` and return the result. -655 -656 If `filler` is a function, it takes the two items surrounding the gap -657 that is about to be filled and produces a new value to be inserted. +649 >>> L[3, 5, 2].fill_right(0, 5) +650 [3, 5, 2, 0, 0, 0, 0, 0] +651 >>> L[3, 5, 2].fill_right(sum, 3) +652 [3, 5, 2, 10, 20, 40] +653 >>> list().fill_right(1, 10) +654 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +655 >>> L[3, 5, 2].fill_right(0, -1) +656 *- ValueError: the number of times to fill cannot be negative -* +657 """ 658 -659 .. warning:: The list must contain at least two items. -660 -661 >>> L[3, 5, 2].interleave(0) -662 [3, 0, 5, 0, 2] -663 >>> L[3, 5, 2].interleave(operator.add) -664 [3, 8, 5, 7, 2] -665 >>> L[0].interleave(1) -666 *- ValueError: list has no gap to be filled -* -667 >>> list().interleave(0) -668 *- ValueError: list has no gap to be filled -* -669 """ -670 -671 if len(self) <= 1: -672 raise ValueError("list has no gap to be filled") -673 -674 returned_list = self.__class__([self.head]) -675 -676 for i in range(1, len(self)): -677 returned_list.append( -678 filler(self[i - 1], self[i]) if callable(filler) else filler, -679 ) -680 returned_list.append(self[i]) +659 if n < 0: +660 msg = "the number of times to fill cannot be negative" +661 raise ValueError(msg) +662 +663 returned_list = self.copy() +664 +665 for _ in range(n): +666 returned_list.append(filler(returned_list) if callable(filler) else filler) +667 +668 return returned_list +669 +670 def interleave( +671 self, +672 filler: _T | collections.abc.Callable[[_T, _T], _T], +673 ) -> typing_extensions.Self: +674 """ +675 Fill in-between the items with `filler` and return the result. +676 +677 If `filler` is a function, it takes the two items surrounding the gap +678 that is about to be filled and produces a new value to be inserted. +679 +680 .. warning:: The list must contain at least two items. 681 -682 return returned_list -683 -684 gap_fill = interleave -685 """ -686 .. warning:: This alias is deprecated. -687 -688 Alias of `interleave`. -689 """ -690 -691 def select( -692 self, -693 indexes: collections.abc.Sequence[int], -694 ) -> typing_extensions.Self: -695 """ -696 Select items at provided indexes. If an index is present several -697 times, this will be reflected in the resulting list. -698 -699 .. warning:: All the indexes must be in bounds. -700 -701 >>> L[3, 5, 2].select([1, 2, 0, 0]) -702 [5, 2, 3, 3] -703 >>> list().select([]) -704 [] -705 >>> L[3, 5, 2].select([4, 1]) -706 *- IndexError: index 4 is out of bounds -* -707 """ -708 -709 returned_list = self.__class__() -710 -711 for index in indexes: -712 if index >= len(self) or index < -len(self): -713 raise IndexError(f"index {index} is out of bounds") -714 -715 returned_list.append(self[index]) -716 -717 return returned_list -718 -719 def take(self, n: int) -> typing_extensions.Self: -720 """ -721 Take `n` items from the list and return them. +682 >>> L[3, 5, 2].interleave(0) +683 [3, 0, 5, 0, 2] +684 >>> L[3, 5, 2].interleave(operator.add) +685 [3, 8, 5, 7, 2] +686 >>> L[0].interleave(1) +687 *- ValueError: list has no gap to be filled -* +688 >>> list().interleave(0) +689 *- ValueError: list has no gap to be filled -* +690 """ +691 +692 if len(self) <= 1: +693 msg = "list has no gap to be filled" +694 raise ValueError(msg) +695 +696 returned_list = self.__class__([self.head]) +697 +698 for i in range(1, len(self)): +699 returned_list.append( +700 filler(self[i - 1], self[i]) if callable(filler) else filler, +701 ) +702 returned_list.append(self[i]) +703 +704 return returned_list +705 +706 gap_fill = interleave +707 """ +708 .. warning:: This alias is deprecated. +709 +710 Alias of `interleave`. +711 """ +712 +713 def select( +714 self, +715 indexes: collections.abc.Sequence[int], +716 ) -> typing_extensions.Self: +717 """ +718 Select items at provided indexes. If an index is present several +719 times, this will be reflected in the resulting list. +720 +721 .. warning:: All the indexes must be in bounds. 722 -723 .. warning:: `n` must be non-negative and less than the list length. -724 -725 >>> L[3, 5, 2].take(2) -726 [3, 5] -727 >>> L[3, 5, 2].take(0) -728 [] -729 >>> L[3, 5, 2].take(-1) -730 *- ValueError: cannot take a negative amount of items -* -731 >>> L[3, 5, 2].take(5) -732 *- ValueError: cannot take more items than the list contains -* -733 """ -734 -735 if n < 0: -736 raise ValueError("cannot take a negative amount of items") +723 >>> L[3, 5, 2].select([1, 2, 0, 0]) +724 [5, 2, 3, 3] +725 >>> list().select([]) +726 [] +727 >>> L[3, 5, 2].select([4, 1]) +728 *- IndexError: index 4 is out of bounds -* +729 """ +730 +731 returned_list = self.__class__() +732 +733 for index in indexes: +734 if index >= len(self) or index < -len(self): +735 msg = f"index {index} is out of bounds" +736 raise IndexError(msg) 737 -738 if n > len(self): -739 raise ValueError("cannot take more items than the list contains") -740 -741 return self.__class__(self[i] for i in range(n)) -742 -743 def take_right(self, n: int) -> typing_extensions.Self: -744 """ -745 Take `n` items from the right of the list and return them. -746 -747 List original order is preserved. -748 -749 .. warning:: `n` must be non-negative and less than the list length. -750 -751 >>> L[3, 5, 2].take_right(2) -752 [5, 2] -753 >>> L[3, 5, 2].take_right(0) -754 [] -755 >>> L[3, 5, 2].take_right(-1) -756 *- ValueError: cannot take a negative amount of items -* -757 >>> L[3, 5, 2].take_right(5) -758 *- ValueError: cannot take more items than the list contains -* -759 """ -760 -761 if n < 0: -762 raise ValueError("cannot take a negative amount of items") -763 -764 if n > len(self): -765 raise ValueError("cannot take more items than the list contains") -766 -767 return self.__class__(item for item in self[len(self) - n :]) -768 -769 def drop(self, n: int) -> typing_extensions.Self: -770 """ -771 Drop `n` items from the list and return the rest. -772 -773 .. warning:: `n` must be non-negative and less than the list length. -774 -775 >>> L[3, 5, 2].drop(2) -776 [2] -777 >>> L[3, 5, 2].drop(0) -778 [3, 5, 2] -779 >>> L[3, 5, 2].drop(-1) -780 *- ValueError: cannot drop a negative amount of items -* -781 >>> L[3, 5, 2].drop(5) -782 *- ValueError: cannot drop more items than the list contains -* -783 """ -784 -785 if n < 0: -786 raise ValueError("cannot drop a negative amount of items") -787 -788 if n > len(self): -789 raise ValueError("cannot drop more items than the list contains") -790 -791 return self.__class__(self[n:]) -792 -793 def drop_right(self, n: int) -> typing_extensions.Self: -794 """ -795 Drop `n` items from the right of the list and return the rest. -796 -797 .. warning:: `n` must be non-negative and less than the list length. -798 -799 >>> L[3, 5, 2].drop_right(2) -800 [3] -801 >>> L[3, 5, 2].drop_right(0) -802 [3, 5, 2] -803 >>> L[3, 5, 2].drop_right(-1) -804 *- ValueError: cannot drop a negative amount of items -* -805 >>> L[3, 5, 2].drop_right(5) -806 *- ValueError: cannot drop more items than the list contains -* -807 """ -808 -809 if n < 0: -810 raise ValueError("cannot drop a negative amount of items") +738 returned_list.append(self[index]) +739 +740 return returned_list +741 +742 def take(self, n: int) -> typing_extensions.Self: +743 """ +744 Take `n` items from the list and return them. +745 +746 .. warning:: `n` must be non-negative and less than the list length. +747 +748 >>> L[3, 5, 2].take(2) +749 [3, 5] +750 >>> L[3, 5, 2].take(0) +751 [] +752 >>> L[3, 5, 2].take(-1) +753 *- ValueError: cannot take a negative amount of items -* +754 >>> L[3, 5, 2].take(5) +755 *- ValueError: cannot take more items than the list contains -* +756 """ +757 +758 if n < 0: +759 msg = "cannot take a negative amount of items" +760 raise ValueError(msg) +761 +762 if n > len(self): +763 msg = "cannot take more items than the list contains" +764 raise ValueError(msg) +765 +766 return self.__class__(self[i] for i in range(n)) +767 +768 def take_right(self, n: int) -> typing_extensions.Self: +769 """ +770 Take `n` items from the right of the list and return them. +771 +772 List original order is preserved. +773 +774 .. warning:: `n` must be non-negative and less than the list length. +775 +776 >>> L[3, 5, 2].take_right(2) +777 [5, 2] +778 >>> L[3, 5, 2].take_right(0) +779 [] +780 >>> L[3, 5, 2].take_right(-1) +781 *- ValueError: cannot take a negative amount of items -* +782 >>> L[3, 5, 2].take_right(5) +783 *- ValueError: cannot take more items than the list contains -* +784 """ +785 +786 if n < 0: +787 msg = "cannot take a negative amount of items" +788 raise ValueError(msg) +789 +790 if n > len(self): +791 msg = "cannot take more items than the list contains" +792 raise ValueError(msg) +793 +794 return self.__class__(item for item in self[len(self) - n :]) +795 +796 def drop(self, n: int) -> typing_extensions.Self: +797 """ +798 Drop `n` items from the list and return the rest. +799 +800 .. warning:: `n` must be non-negative and less than the list length. +801 +802 >>> L[3, 5, 2].drop(2) +803 [2] +804 >>> L[3, 5, 2].drop(0) +805 [3, 5, 2] +806 >>> L[3, 5, 2].drop(-1) +807 *- ValueError: cannot drop a negative amount of items -* +808 >>> L[3, 5, 2].drop(5) +809 *- ValueError: cannot drop more items than the list contains -* +810 """ 811 -812 if n > len(self): -813 raise ValueError("cannot drop more items than the list contains") -814 -815 return self.__class__(self[: len(self) - n]) -816 -817 def slice(self, start: int, stop: int) -> typing_extensions.Self: -818 """ -819 Slice the list from `start` to `stop` and return the result. -820 -821 This method is NOT equivalent to the `self[start:stop]` notation. -822 If `start` or `stop` are out of bounds of the list or `start` is -823 greater than `stop`, it will raise an exception. -824 -825 .. warning:: `start` and `stop` must be in bounds. -826 -827 >>> L[2, 4, 8, 16, 32].slice(1, 3) -828 [4, 8, 16] -829 >>> L[2, 4, 8, 16, 32].slice(0, 2) -830 [2, 4, 8] -831 >>> L[2, 4, 8, 16, 32].slice(3, 5) -832 [8, 16, 32] -833 >>> L[2, 4, 8, 16, 32].slice(2, 2) -834 [8] -835 >>> L[2, 4, 8, 16, 32].slice(1, 10) -836 *- ValueError: slice out of bounds -* -837 >>> L[2, 4, 8, 16, 32].slice(4, 2) -838 *- ValueError: start cannot be greater than stop -* -839 -840 Tip: if `start` is 0, you can do `.take(stop - 1)` instead. -841 Symmetrically, if `stop` is the index of the last item, go for a -842 `.drop(start)`! -843 """ -844 -845 if start > stop: -846 raise ValueError("start cannot be greater than stop") +812 if n < 0: +813 msg = "cannot drop a negative amount of items" +814 raise ValueError(msg) +815 +816 if n > len(self): +817 msg = "cannot drop more items than the list contains" +818 raise ValueError(msg) +819 +820 return self.__class__(self[n:]) +821 +822 def drop_right(self, n: int) -> typing_extensions.Self: +823 """ +824 Drop `n` items from the right of the list and return the rest. +825 +826 .. warning:: `n` must be non-negative and less than the list length. +827 +828 >>> L[3, 5, 2].drop_right(2) +829 [3] +830 >>> L[3, 5, 2].drop_right(0) +831 [3, 5, 2] +832 >>> L[3, 5, 2].drop_right(-1) +833 *- ValueError: cannot drop a negative amount of items -* +834 >>> L[3, 5, 2].drop_right(5) +835 *- ValueError: cannot drop more items than the list contains -* +836 """ +837 +838 if n < 0: +839 msg = "cannot drop a negative amount of items" +840 raise ValueError(msg) +841 +842 if n > len(self): +843 msg = "cannot drop more items than the list contains" +844 raise ValueError(msg) +845 +846 return self.__class__(self[: len(self) - n]) 847 -848 if start < 0 or stop >= len(self): -849 raise ValueError("slice out of bounds") -850 -851 return self.__class__(self[start : stop + 1]) -852 -853 def partition( -854 self, -855 index: int, -856 ) -> tuple[typing_extensions.Self, _T, typing_extensions.Self]: -857 """ -858 Return the item at index `index`, but also the two list slices -859 before and after that item, in this order: (left, item, right). -860 -861 .. warning:: The list must be non-empty, and the partition index in bounds. -862 -863 >>> L[2, 4, 8, 16, 32].partition(2) -864 ([2, 4], 8, [16, 32]) -865 >>> L[2, 4, 8, 16, 32].partition(0) -866 ([], 2, [4, 8, 16, 32]) -867 >>> L[2, 4, 8, 16, 32].partition(4) -868 ([2, 4, 8, 16], 32, []) -869 >>> L[2, 4, 8, 16, 32].partition(-2) -870 *- IndexError: partition index cannot be out of bounds -* -871 >>> list().partition(2) -872 *- TypeError: cannot partition an empty list -* -873 """ -874 -875 if not self: -876 raise TypeError("cannot partition an empty list") -877 -878 if not (0 <= index < len(self)): -879 raise IndexError("partition index cannot be out of bounds") -880 -881 return self.take(index), self[index], self.drop(index + 1) -882 -883 def bisect( -884 self, -885 index: int, -886 ) -> tuple[typing_extensions.Self, typing_extensions.Self]: -887 """ -888 Bisect the list after `index` elements and return a pair of the produced -889 lists. -890 -891 .. warning:: The list must be non-empty. -892 -893 >>> L[2, 4, 8, 16, 32].bisect(2) -894 ([2, 4], [8, 16, 32]) -895 >>> L[2, 4, 8, 16, 32].bisect(0) -896 ([], [2, 4, 8, 16, 32]) -897 >>> L[2, 4, 8, 16, 32].bisect(8) -898 ([2, 4, 8, 16, 32], []) -899 >>> L[2, 4, 8, 16, 32].bisect(-3) -900 ([], [2, 4, 8, 16, 32]) -901 >>> list().bisect(2) -902 *- TypeError: cannot bisect an empty list -* -903 """ -904 -905 if not self: -906 raise TypeError("cannot bisect an empty list") +848 def slice(self, start: int, stop: int) -> typing_extensions.Self: +849 """ +850 Slice the list from `start` to `stop` and return the result. +851 +852 This method is NOT equivalent to the `self[start:stop]` notation. +853 If `start` or `stop` are out of bounds of the list or `start` is +854 greater than `stop`, it will raise an exception. +855 +856 .. warning:: `start` and `stop` must be in bounds. +857 +858 >>> L[2, 4, 8, 16, 32].slice(1, 3) +859 [4, 8, 16] +860 >>> L[2, 4, 8, 16, 32].slice(0, 2) +861 [2, 4, 8] +862 >>> L[2, 4, 8, 16, 32].slice(3, 5) +863 [8, 16, 32] +864 >>> L[2, 4, 8, 16, 32].slice(2, 2) +865 [8] +866 >>> L[2, 4, 8, 16, 32].slice(1, 10) +867 *- ValueError: slice out of bounds -* +868 >>> L[2, 4, 8, 16, 32].slice(4, 2) +869 *- ValueError: start cannot be greater than stop -* +870 +871 Tip: if `start` is 0, you can do `.take(stop - 1)` instead. +872 Symmetrically, if `stop` is the index of the last item, go for a +873 `.drop(start)`! +874 """ +875 +876 if start > stop: +877 msg = "start cannot be greater than stop" +878 raise ValueError(msg) +879 +880 if start < 0 or stop >= len(self): +881 msg = "slice out of bounds" +882 raise ValueError(msg) +883 +884 return self.__class__(self[start : stop + 1]) +885 +886 def partition( +887 self, +888 index: int, +889 ) -> tuple[typing_extensions.Self, _T, typing_extensions.Self]: +890 """ +891 Return the item at index `index`, but also the two list slices +892 before and after that item, in this order: (left, item, right). +893 +894 .. warning:: The list must be non-empty, and the partition index in bounds. +895 +896 >>> L[2, 4, 8, 16, 32].partition(2) +897 ([2, 4], 8, [16, 32]) +898 >>> L[2, 4, 8, 16, 32].partition(0) +899 ([], 2, [4, 8, 16, 32]) +900 >>> L[2, 4, 8, 16, 32].partition(4) +901 ([2, 4, 8, 16], 32, []) +902 >>> L[2, 4, 8, 16, 32].partition(-2) +903 *- IndexError: partition index cannot be out of bounds -* +904 >>> list().partition(2) +905 *- TypeError: cannot partition an empty list -* +906 """ 907 -908 _n = _minmax(index, 0, len(self)) -909 -910 return self.take(_n), self.drop(_n) +908 if not self: +909 msg = "cannot partition an empty list" +910 raise TypeError(msg) 911 -912 def trisect( -913 self, -914 first_index: int, -915 second_index: int, -916 ) -> tuple[ -917 typing_extensions.Self, -918 typing_extensions.Self, -919 typing_extensions.Self, -920 ]: -921 """ -922 Trisect the list at `first_index` and `second_index` and return a -923 triple of the produced lists. -924 -925 The left and right cutting indexes are determined by the smallest and -926 largest value of the two arguments respectively ; `first_index` is not -927 required to be smaller. -928 -929 .. warning:: The list must be non-empty. -930 """ -931 -932 if not self: -933 raise TypeError("cannot trisect an empty list") -934 -935 _left = _minmax(min(first_index, second_index), 0, len(self)) -936 _right = _minmax(max(first_index, second_index), 0, len(self)) -937 -938 return self.take(_left), self[_left:_right], self.drop(_right) +912 if not (0 <= index < len(self)): +913 msg = "partition index cannot be out of bounds" +914 raise IndexError(msg) +915 +916 return self.take(index), self[index], self.drop(index + 1) +917 +918 def bisect( +919 self, +920 index: int, +921 ) -> tuple[typing_extensions.Self, typing_extensions.Self]: +922 """ +923 Bisect the list after `index` elements and return a pair of the produced +924 lists. +925 +926 .. warning:: The list must be non-empty. +927 +928 >>> L[2, 4, 8, 16, 32].bisect(2) +929 ([2, 4], [8, 16, 32]) +930 >>> L[2, 4, 8, 16, 32].bisect(0) +931 ([], [2, 4, 8, 16, 32]) +932 >>> L[2, 4, 8, 16, 32].bisect(8) +933 ([2, 4, 8, 16, 32], []) +934 >>> L[2, 4, 8, 16, 32].bisect(-3) +935 ([], [2, 4, 8, 16, 32]) +936 >>> list().bisect(2) +937 *- TypeError: cannot bisect an empty list -* +938 """ +939 +940 if not self: +941 msg = "cannot bisect an empty list" +942 raise TypeError(msg) +943 +944 _n = _minmax(index, 0, len(self)) +945 +946 return self.take(_n), self.drop(_n) +947 +948 def trisect( +949 self, +950 first_index: int, +951 second_index: int, +952 ) -> tuple[ +953 typing_extensions.Self, +954 typing_extensions.Self, +955 typing_extensions.Self, +956 ]: +957 """ +958 Trisect the list at `first_index` and `second_index` and return a +959 triple of the produced lists. +960 +961 The left and right cutting indexes are determined by the smallest and +962 largest value of the two arguments respectively ; `first_index` is not +963 required to be smaller. +964 +965 .. warning:: The list must be non-empty. +966 """ +967 +968 if not self: +969 msg = "cannot trisect an empty list" +970 raise TypeError(msg) +971 +972 _left = _minmax(min(first_index, second_index), 0, len(self)) +973 _right = _minmax(max(first_index, second_index), 0, len(self)) +974 +975 return self.take(_left), self[_left:_right], self.drop(_right)
42 """ 43 44 if not self: -45 raise TypeError("empty list has no head") -46 -47 return self[0] +45 msg = "empty list has no head" +46 raise TypeError(msg) +47 +48 return self[0]
49 @property -50 def tail(self) -> typing_extensions.Self: -51 """ -52 List without its first item. -53 -54 .. warning:: The list must be non-empty. -55 -56 >>> L[3, 5, 2].tail -57 [5, 2] -58 >>> list().tail -59 *- TypeError: empty list has no tail -* -60 """ -61 -62 if not self: -63 raise TypeError("empty list has no tail") -64 -65 return self.__class__(self[1:]) +@@ -1241,23 +1281,24 @@50 @property +51 def tail(self) -> typing_extensions.Self: +52 """ +53 List without its first item. +54 +55 .. warning:: The list must be non-empty. +56 +57 >>> L[3, 5, 2].tail +58 [5, 2] +59 >>> list().tail +60 *- TypeError: empty list has no tail -* +61 """ +62 +63 if not self: +64 msg = "empty list has no tail" +65 raise TypeError(msg) +66 +67 return self.__class__(self[1:])The list must be non-empty.
67 @property -68 def init(self) -> typing_extensions.Self: -69 """ -70 List without its last item. -71 -72 .. warning:: The list must be non-empty. +@@ -1289,23 +1330,24 @@69 @property +70 def init(self) -> typing_extensions.Self: +71 """ +72 List without its last item. 73 -74 >>> L[3, 5, 2].init -75 [3, 5] -76 >>> list().init -77 *- TypeError: empty list has no init -* -78 """ -79 -80 if not self: -81 raise TypeError("empty list has no init") -82 -83 return self.__class__(self[:-1]) +74 .. warning:: The list must be non-empty. +75 +76 >>> L[3, 5, 2].init +77 [3, 5] +78 >>> list().init +79 *- TypeError: empty list has no init -* +80 """ +81 +82 if not self: +83 msg = "empty list has no init" +84 raise TypeError(msg) +85 +86 return self.__class__(self[:-1])The list must be non-empty.
85 @property - 86 def last(self) -> _T: - 87 """ - 88 Last item of the list. - 89 - 90 .. warning:: The list must be non-empty. - 91 - 92 >>> L[3, 5, 2].last - 93 2 - 94 >>> list().last - 95 *- TypeError: empty list has no last -* - 96 """ - 97 - 98 if not self: - 99 raise TypeError("empty list has no last") +@@ -1331,7 +1373,7 @@88 @property + 89 def last(self) -> _T: + 90 """ + 91 Last item of the list. + 92 + 93 .. warning:: The list must be non-empty. + 94 + 95 >>> L[3, 5, 2].last + 96 2 + 97 >>> list().last + 98 *- TypeError: empty list has no last -* + 99 """ 100 -101 return self[-1] +101 if not self: +102 msg = "empty list has no last" +103 raise TypeError(msg) +104 +105 return self[-1]The list must be non-empty.
- + def prepend(self, item: ~_T) -> None: @@ -1339,17 +1381,17 @@-The list must be non-empty.
103 def prepend(self, item: _T) -> None: -104 """ -105 Add an item at the beginning of the list. -106 -107 >>> l = L[3, 5, 2] -108 >>> l.prepend(-2) -109 >>> print(l) -110 [-2, 3, 5, 2] -111 """ -112 -113 self.insert(0, item) +@@ -1369,7 +1411,7 @@107 def prepend(self, item: _T) -> None: +108 """ +109 Add an item at the beginning of the list. +110 +111 >>> l = L[3, 5, 2] +112 >>> l.prepend(-2) +113 >>> print(l) +114 [-2, 3, 5, 2] +115 """ +116 +117 self.insert(0, item)The list must be non-empty.
- + def reversed(self) -> Self: @@ -1377,16 +1419,16 @@-The list must be non-empty.
115 def reversed(self) -> typing_extensions.Self: -116 """ -117 Return a reversed version of the list. -118 -119 >>> L[1, 2, 3].reversed() -120 [3, 2, 1] -121 """ +@@ -1404,7 +1446,7 @@119 def reversed(self) -> typing_extensions.Self: +120 """ +121 Return a reversed version of the list. 122 -123 # we avoid constructing a whole `reversed` object -124 return self.__class__(self.__reversed__()) +123 >>> L[1, 2, 3].reversed() +124 [3, 2, 1] +125 """ +126 +127 # we avoid constructing a whole `reversed` object +128 return self.__class__(self.__reversed__())The list must be non-empty.
- + def sorted( self, *, key: 'collections.abc.Callable[[_T], _typeshed.SupportsRichComparison] | None' = None, reverse: bool = False) -> Self: @@ -1412,23 +1454,23 @@-The list must be non-empty.
126 def sorted( -127 self, -128 *, -129 key: collections.abc.Callable[[_T], _typeshed.SupportsRichComparison] -130 | None = None, -131 reverse: bool = False, -132 ) -> typing_extensions.Self: -133 """ -134 Return a sorted version of the list. -135 -136 >>> L[3, 5, 2].sorted() -137 [2, 3, 5] -138 >>> list("gala").sorted(key=ord) -139 ["a", "a", "g", "l"] -140 """ -141 -142 return self.__class__(sorted(self, key=key, reverse=reverse)) # type: ignore +@@ -1448,7 +1490,7 @@130 def sorted( +131 self, +132 *, +133 key: collections.abc.Callable[[_T], _typeshed.SupportsRichComparison] +134 | None = None, +135 reverse: bool = False, +136 ) -> typing_extensions.Self: +137 """ +138 Return a sorted version of the list. +139 +140 >>> L[3, 5, 2].sorted() +141 [2, 3, 5] +142 >>> list("gala").sorted(key=ord) +143 ["a", "a", "g", "l"] +144 """ +145 +146 return self.__class__(sorted(self, key=key, reverse=reverse)) # pyright: ignore[reportCallIssue, reportArgumentType]The list must be non-empty.
- + def shuffled(self) -> Self: @@ -1456,22 +1498,22 @@-The list must be non-empty.
144 def shuffled(self) -> typing_extensions.Self: -145 """ -146 Return a shuffled version of the list. -147 -148 >>> L[3, 5, 2].shuffled() -149 [5, 2, 3] -150 >>> L[3, 5, 2].shuffled() -151 [2, 5, 3] -152 >>> list().shuffled() -153 [] -154 """ -155 -156 result = self.copy() -157 random.shuffle(result) -158 -159 return result +@@ -1493,7 +1535,7 @@148 def shuffled(self) -> typing_extensions.Self: +149 """ +150 Return a shuffled version of the list. +151 +152 >>> L[3, 5, 2].shuffled() +153 [5, 2, 3] +154 >>> L[3, 5, 2].shuffled() +155 [2, 5, 3] +156 >>> list().shuffled() +157 [] +158 """ +159 +160 result = self.copy() +161 random.shuffle(result) +162 +163 return resultThe list must be non-empty.
- + def map( self, function: collections.abc.Callable[[~_T], ~_U]) -> list[~_U]: @@ -1501,23 +1543,23 @@-The list must be non-empty.
161 def map(self, function: collections.abc.Callable[[_T], _U]) -> list[_U]: -162 """ -163 Apply `function` on each item of the list. -164 -165 >>> L[3, 5, 2].map(str) -166 ["3", "5", "2"] -167 >>> L[3, 5, 2].map(lambda n: n * 2) -168 [6, 10, 4] -169 >>> list().map(lambda n: n * 20) -170 [] -171 """ -172 -173 # subclasses' `map` return type is also marked as `list` because we -174 # cannot make the container generic -- this requires Higher-Kinded -175 # Types, which Python does not support (yet? hopefully!) +@@ -1539,7 +1581,7 @@165 def map(self, function: collections.abc.Callable[[_T], _U]) -> list[_U]: +166 """ +167 Apply `function` on each item of the list. +168 +169 >>> L[3, 5, 2].map(str) +170 ["3", "5", "2"] +171 >>> L[3, 5, 2].map(lambda n: n * 2) +172 [6, 10, 4] +173 >>> list().map(lambda n: n * 20) +174 [] +175 """ 176 -177 return typing.cast(list[_U], self.__class__(map(function, self))) +177 # subclasses' `map` return type is also marked as `list` because we +178 # cannot make the container generic -- this requires Higher-Kinded +179 # Types, which Python does not support (yet? hopefully!) +180 +181 return typing.cast(list[_U], self.__class__(map(function, self)))The list must be non-empty.
- + def rotate(self, n: int = 1) -> Self: @@ -1547,43 +1589,44 @@-The list must be non-empty.
179 def rotate(self, n: int = 1) -> typing_extensions.Self: -180 """ -181 Shift the list `n` times to the right. The items that overflow get prepended. -182 -183 If `n` is negative, the shift goes to the left. -184 -185 .. warning:: The list must be non-empty. +@@ -1615,7 +1658,7 @@183 def rotate(self, n: int = 1) -> typing_extensions.Self: +184 """ +185 Shift the list `n` times to the right. The items that overflow get prepended. 186 -187 >>> L[3, 5, 2].rotate() -188 [2, 3, 5] -189 >>> L[3, 5, 2].rotate(2) -190 [5, 2, 3] -191 >>> L[3, 5, 2].rotate(-1) -192 [5, 2, 3] -193 >>> list().rotate() -194 *- TypeError: empty list cannot be rotated -* -195 """ -196 -197 if not self: -198 raise TypeError("empty list cannot be rotated") -199 -200 if n == 0: -201 return self -202 -203 returned_list = self.copy() +187 If `n` is negative, the shift goes to the left. +188 +189 .. warning:: The list must be non-empty. +190 +191 >>> L[3, 5, 2].rotate() +192 [2, 3, 5] +193 >>> L[3, 5, 2].rotate(2) +194 [5, 2, 3] +195 >>> L[3, 5, 2].rotate(-1) +196 [5, 2, 3] +197 >>> list().rotate() +198 *- TypeError: empty list cannot be rotated -* +199 """ +200 +201 if not self: +202 msg = "empty list cannot be rotated" +203 raise TypeError(msg) 204 -205 if n > 0: -206 xpend_method = returned_list.prepend -207 popped_index = -1 -208 else: -209 xpend_method = returned_list.append -210 popped_index = 0 -211 -212 for _ in range(abs(n)): -213 xpend_method(returned_list.pop(popped_index)) -214 -215 return returned_list +205 if n == 0: +206 return self +207 +208 returned_list = self.copy() +209 +210 if n > 0: +211 xpend_method = returned_list.prepend +212 popped_index = -1 +213 else: +214 xpend_method = returned_list.append +215 popped_index = 0 +216 +217 for _ in range(abs(n)): +218 xpend_method(returned_list.pop(popped_index)) +219 +220 return returned_listThe list must be non-empty.
- + def filter(self, function: collections.abc.Callable[[~_T], bool]) -> Self: @@ -1623,22 +1666,22 @@-The list must be non-empty.
217 def filter( -218 self, -219 function: collections.abc.Callable[[_T], bool], -220 ) -> typing_extensions.Self: -221 """ -222 Discard each item `i` of the list if `function(i)` is `False`. -223 -224 >>> L[3, 5, 2].filter(lambda n: n % 2 == 1) -225 [3, 5] -226 >>> L["hello", "hola", "bonjour"].filter(lambda s: "l" in s) -227 ["hello", "hola"] -228 >>> list().filter(lambda n: n > 0) -229 [] -230 """ -231 -232 return self.__class__(filter(function, self)) +@@ -1660,7 +1703,7 @@222 def filter( +223 self, +224 function: collections.abc.Callable[[_T], bool], +225 ) -> typing_extensions.Self: +226 """ +227 Discard each item `i` of the list if `function(i)` is `False`. +228 +229 >>> L[3, 5, 2].filter(lambda n: n % 2 == 1) +230 [3, 5] +231 >>> L["hello", "hola", "bonjour"].filter(lambda s: "l" in s) +232 ["hello", "hola"] +233 >>> list().filter(lambda n: n > 0) +234 [] +235 """ +236 +237 return self.__class__(filter(function, self))The list must be non-empty.
- + def mask(self, mask_seq: collections.abc.Sequence[bool]) -> Self: @@ -1668,29 +1711,30 @@-The list must be non-empty.
234 def mask( -235 self, -236 mask_seq: collections.abc.Sequence[bool], -237 ) -> typing_extensions.Self: -238 """ -239 Keep every item at index `i` of the list if the corresponding -240 item at index `i` of the mask sequence is `True` ; else, discard -241 it. Return the filtered list. -242 -243 .. warning:: The mask sequence must be of the same length as the list. -244 -245 >>> L[3, 5, 2].mask([True, False, True]) -246 [3, 2] -247 >>> list().mask([]) -248 [] -249 >>> L[3, 5, 2].mask([True, False]) -250 *- TypeError: mask length must be the same as the list -* -251 """ -252 -253 if len(self) != len(mask_seq): -254 raise TypeError("mask length must be the same as the list") -255 -256 return self.__class__(item for item, bit in zip(self, mask_seq) if bit) +@@ -1720,7 +1764,7 @@239 def mask( +240 self, +241 mask_seq: collections.abc.Sequence[bool], +242 ) -> typing_extensions.Self: +243 """ +244 Keep every item at index `i` of the list if the corresponding +245 item at index `i` of the mask sequence is `True` ; else, discard +246 it. Return the filtered list. +247 +248 .. warning:: The mask sequence must be of the same length as the list. +249 +250 >>> L[3, 5, 2].mask([True, False, True]) +251 [3, 2] +252 >>> list().mask([]) +253 [] +254 >>> L[3, 5, 2].mask([True, False]) +255 *- TypeError: mask length must be the same as the list -* +256 """ +257 +258 if len(self) != len(mask_seq): +259 msg = "mask length must be the same as the list" +260 raise TypeError(msg) +261 +262 return self.__class__(item for item, bit in zip(self, mask_seq) if bit)The mask seque
- + def deduplicate(self) -> Self: @@ -1728,26 +1772,26 @@-The mask seque
258 def deduplicate(self) -> typing_extensions.Self: -259 """ -260 Remove duplicate elements from left to right (and keep original ones). -261 Return the deduplicated list. -262 -263 >>> L[3, 0, 0, 1, 18].deduplicate() -264 [3, 0, 1, 18] -265 >>> L["hello", "hello", "world", "world"].deduplicate() -266 ["hello", "world"] -267 >>> list().deduplicate() -268 [] -269 """ -270 -271 returned_list: typing_extensions.Self = self.__class__() -272 -273 for elem in self: -274 if elem not in returned_list: -275 returned_list.append(elem) +@@ -1770,7 +1814,7 @@264 def deduplicate(self) -> typing_extensions.Self: +265 """ +266 Remove duplicate elements from left to right (and keep original ones). +267 Return the deduplicated list. +268 +269 >>> L[3, 0, 0, 1, 18].deduplicate() +270 [3, 0, 1, 18] +271 >>> L["hello", "hello", "world", "world"].deduplicate() +272 ["hello", "world"] +273 >>> list().deduplicate() +274 [] +275 """ 276 -277 return returned_list +277 returned_list: typing_extensions.Self = self.__class__() +278 +279 for elem in self: +280 if elem not in returned_list: +281 returned_list.append(elem) +282 +283 return returned_listThe mask seque
- + def reduce(self, function: collections.abc.Callable[[~_T, ~_T], ~_T]) -> ~_T: @@ -1778,26 +1822,27 @@-The mask seque
279 def reduce(self, function: collections.abc.Callable[[_T, _T], _T]) -> _T: -280 """ -281 "Insert" an operator (called a reducing function) between each item -282 from left to right and return the result. -283 -284 The first item of the list is used as the leftmost value ; -285 therefore, if the list is empty, it will raise an exception. -286 -287 .. warning:: The list must be non-empty. -288 -289 >>> L[3, 5, 2].reduce(operator.add) # (3 + 5) + 2 -290 10 -291 >>> list().reduce(operator.mul) -292 *- TypeError: the list to reduce cannot be empty -* -293 """ +@@ -1827,7 +1872,7 @@285 def reduce(self, function: collections.abc.Callable[[_T, _T], _T]) -> _T: +286 """ +287 "Insert" an operator (called a reducing function) between each item +288 from left to right and return the result. +289 +290 The first item of the list is used as the leftmost value ; +291 therefore, if the list is empty, it will raise an exception. +292 +293 .. warning:: The list must be non-empty. 294 -295 if not self: -296 raise TypeError("the list to reduce cannot be empty") -297 -298 return functools.reduce(function, self) +295 >>> L[3, 5, 2].reduce(operator.add) # (3 + 5) + 2 +296 10 +297 >>> list().reduce(operator.mul) +298 *- TypeError: the list to reduce cannot be empty -* +299 """ +300 +301 if not self: +302 msg = "the list to reduce cannot be empty" +303 raise TypeError(msg) +304 +305 return functools.reduce(function, self)The list must be non-empty.
- + def reduce_right(self, function: collections.abc.Callable[[~_T, ~_T], ~_T]) -> ~_T: @@ -1835,31 +1880,32 @@-The list must be non-empty.
300 def reduce_right( -301 self, -302 function: collections.abc.Callable[[_T, _T], _T], -303 ) -> _T: -304 """ -305 "Insert" an operator (called a reducing function) between each item -306 from right to left and return the result. -307 -308 The last item of the list is used as the leftmost value ; -309 therefore, if the list is empty, it will raise an exception. -310 -311 .. warning:: The list must be non-empty. -312 -313 >>> L[3, 5, 2].reduce_right(operator.add) # 3 + (5 + 2) -314 10 -315 >>> L[3, 5, 2].reduce_right(operator.sub) # 3 - (5 - 2) -316 0 -317 >>> list().reduce_right(operator.add) -318 *- TypeError: the list to reduce cannot be empty -* -319 """ -320 -321 if not self: -322 raise TypeError("the list to reduce cannot be empty") -323 -324 return functools.reduce(lambda a, b: function(b, a), self.reversed()) +@@ -1891,7 +1937,7 @@307 def reduce_right( +308 self, +309 function: collections.abc.Callable[[_T, _T], _T], +310 ) -> _T: +311 """ +312 "Insert" an operator (called a reducing function) between each item +313 from right to left and return the result. +314 +315 The last item of the list is used as the leftmost value ; +316 therefore, if the list is empty, it will raise an exception. +317 +318 .. warning:: The list must be non-empty. +319 +320 >>> L[3, 5, 2].reduce_right(operator.add) # 3 + (5 + 2) +321 10 +322 >>> L[3, 5, 2].reduce_right(operator.sub) # 3 - (5 - 2) +323 0 +324 >>> list().reduce_right(operator.add) +325 *- TypeError: the list to reduce cannot be empty -* +326 """ +327 +328 if not self: +329 msg = "the list to reduce cannot be empty" +330 raise TypeError(msg) +331 +332 return functools.reduce(lambda a, b: function(b, a), self.reversed())The list must be non-empty.
- + def fold( self, function: collections.abc.Callable[[~_T, ~_T], ~_T], initial_value: ~_T) -> ~_T: @@ -1899,25 +1945,25 @@-The list must be non-empty.
326 def fold( -327 self, -328 function: collections.abc.Callable[[_T, _T], _T], -329 initial_value: _T, -330 ) -> _T: -331 """ -332 "Insert" an operator (called a reducing function) between each item -333 from left to right and return the result. -334 -335 The `initial_value` is used as the leftmost value, and is the returned -336 value if the list is empty. -337 -338 >>> L[3, 5, 2].fold(operator.add, -3) # ((-3 + 3) + 5) + 2 -339 7 -340 >>> list().fold(operator.mul, 0) -341 0 -342 """ -343 -344 return functools.reduce(function, self, initial_value) +@@ -1941,7 +1987,7 @@334 def fold( +335 self, +336 function: collections.abc.Callable[[_T, _T], _T], +337 initial_value: _T, +338 ) -> _T: +339 """ +340 "Insert" an operator (called a reducing function) between each item +341 from left to right and return the result. +342 +343 The `initial_value` is used as the leftmost value, and is the returned +344 value if the list is empty. +345 +346 >>> L[3, 5, 2].fold(operator.add, -3) # ((-3 + 3) + 5) + 2 +347 7 +348 >>> list().fold(operator.mul, 0) +349 0 +350 """ +351 +352 return functools.reduce(function, self, initial_value)The list must be non-empty.
- + def fold_right( self, function: collections.abc.Callable[[~_T, ~_T], ~_T], initial_value: ~_T) -> ~_T: @@ -1949,29 +1995,29 @@-The list must be non-empty.
346 def fold_right( -347 self, -348 function: collections.abc.Callable[[_T, _T], _T], -349 initial_value: _T, -350 ) -> _T: -351 """ -352 "Insert" an operator (called a reducing function) between each item -353 from right to left and return the result. -354 -355 The `initial_value` is used as the leftmost value, and is the -356 returned value if the list is empty. -357 -358 >>> L[3, 5, 2].fold_right(operator.sub, -3) # -3 - (3 - (5 - 2)) -359 0 -360 >>> list().fold_right(operator.mul, 0) -361 0 -362 """ -363 -364 return functools.reduce( -365 lambda a, b: function(b, a), -366 self.reversed(), -367 initial_value, -368 ) +@@ -1995,7 +2041,7 @@354 def fold_right( +355 self, +356 function: collections.abc.Callable[[_T, _T], _T], +357 initial_value: _T, +358 ) -> _T: +359 """ +360 "Insert" an operator (called a reducing function) between each item +361 from right to left and return the result. +362 +363 The `initial_value` is used as the leftmost value, and is the +364 returned value if the list is empty. +365 +366 >>> L[3, 5, 2].fold_right(operator.sub, -3) # -3 - (3 - (5 - 2)) +367 0 +368 >>> list().fold_right(operator.mul, 0) +369 0 +370 """ +371 +372 return functools.reduce( +373 lambda a, b: function(b, a), +374 self.reversed(), +375 initial_value, +376 )The list must be non-empty.
- + def scan( self, function: collections.abc.Callable[[~_T, ~_T], ~_T], initial_value: ~_T) -> Self: @@ -2003,37 +2049,38 @@-The list must be non-empty.
370 def scan( -371 self, -372 function: collections.abc.Callable[[_T, _T], _T], -373 initial_value: _T, -374 ) -> typing_extensions.Self: -375 """ -376 "Insert" an operator (called a reducing function) between each item -377 from left to right and return the intermediate values followed by the -378 result. -379 -380 The `initial_value` is used as the leftmost value, and is the only -381 value of the returned list if the original list is empty. -382 -383 >>> L[3, 5, 2].scan(operator.add, 0) # [0, (0 + 3), (0 + 3 + 5), (0 + 3 + 5 + 2)] -384 [0, 3, 8, 10] -385 >>> list().scan(operator.add, 0) -386 [0] -387 """ -388 -389 result_tail = self.__class__() +@@ -2045,7 +2092,8 @@378 def scan( +379 self, +380 function: collections.abc.Callable[[_T, _T], _T], +381 initial_value: _T, +382 ) -> typing_extensions.Self: +383 """ +384 "Insert" an operator (called a reducing function) between each item +385 from left to right and return the intermediate values followed by the +386 result. +387 +388 The `initial_value` is used as the leftmost value, and is the only +389 value of the returned list if the original list is empty. 390 -391 if self: -392 head, *tail = self -393 result_tail.extend( -394 self.__class__(tail).scan( -395 function, -396 function(initial_value, head), -397 ), -398 ) +391 >>> # [0, (0 + 3), (0 + 3 + 5), (0 + 3 + 5 + 2)] +392 >>> L[3, 5, 2].scan(operator.add, 0) +393 [0, 3, 8, 10] +394 >>> list().scan(operator.add, 0) +395 [0] +396 """ +397 +398 result_tail = self.__class__() 399 -400 return self.__class__([initial_value]) + result_tail +400 if self: +401 head, *tail = self +402 result_tail.extend( +403 self.__class__(tail).scan( +404 function, +405 function(initial_value, head), +406 ), +407 ) +408 +409 return self.__class__([initial_value]) + result_tailThe list must be non-empty.
value of the returned list if the original list is empty.->>> L[3, 5, 2].scan(operator.add, 0) # [0, (0 + 3), (0 + 3 + 5), (0 + 3 + 5 + 2)] +
>>> # [0, (0 + 3), (0 + 3 + 5), (0 + 3 + 5 + 2)] +>>> L[3, 5, 2].scan(operator.add, 0) [0, 3, 8, 10] >>> list().scan(operator.add, 0) [0] @@ -2058,7 +2106,7 @@
The list must be non-empty.
- + def scan_right( self, function: collections.abc.Callable[[~_T, ~_T], ~_T], initial_value: ~_T) -> Self: @@ -2066,26 +2114,27 @@-The list must be non-empty.
402 def scan_right( -403 self, -404 function: collections.abc.Callable[[_T, _T], _T], -405 initial_value: _T, -406 ) -> typing_extensions.Self: -407 """ -408 "Insert" an operator (called a reducing function) between each item -409 from right to left and return the intermediate values followed by the -410 result. -411 -412 The `initial_value` is used as the leftmost value, and is the only -413 value of the returned list if the original list is empty. -414 -415 >>> L[3, 5, 2].scan_right(operator.add, 0) # [0, (2 + 0), (5 + 2 + 0), (3 + 5 + 2 + 0)] -416 [0, 2, 7, 10] -417 >>> list().scan_right(operator.add, 0) -418 [0] -419 """ +@@ -2097,7 +2146,8 @@411 def scan_right( +412 self, +413 function: collections.abc.Callable[[_T, _T], _T], +414 initial_value: _T, +415 ) -> typing_extensions.Self: +416 """ +417 "Insert" an operator (called a reducing function) between each item +418 from right to left and return the intermediate values followed by the +419 result. 420 -421 return self.reversed().scan(lambda a, b: function(b, a), initial_value) +421 The `initial_value` is used as the leftmost value, and is the only +422 value of the returned list if the original list is empty. +423 +424 >>> # [0, (2 + 0), (5 + 2 + 0), (3 + 5 + 2 + 0)] +425 >>> L[3, 5, 2].scan_right(operator.add, 0) +426 [0, 2, 7, 10] +427 >>> list().scan_right(operator.add, 0) +428 [0] +429 """ +430 +431 return self.reversed().scan(lambda a, b: function(b, a), initial_value)The list must be non-empty.
value of the returned list if the original list is empty.->>> L[3, 5, 2].scan_right(operator.add, 0) # [0, (2 + 0), (5 + 2 + 0), (3 + 5 + 2 + 0)] +
>>> # [0, (2 + 0), (5 + 2 + 0), (3 + 5 + 2 + 0)] +>>> L[3, 5, 2].scan_right(operator.add, 0) [0, 2, 7, 10] >>> list().scan_right(operator.add, 0) [0] @@ -2110,7 +2160,7 @@
The list must be non-empty.
- + def merge( self, function: collections.abc.Callable[[~_T, ~_U], ~_V], other: collections.abc.Sequence[~_U]) -> list[~_V]: @@ -2118,33 +2168,34 @@-The list must be non-empty.
423 def merge( -424 self, -425 function: collections.abc.Callable[[_T, _U], _V], -426 other: collections.abc.Sequence[_U], -427 ) -> list[_V]: -428 """ -429 Build a new list from the result of each `function(s_i, o_i)` where -430 `s_i` and `o_i` are the items at index `i` of `self` and `other` -431 respectively. -432 -433 .. warning:: The list and the sequence must have the same length. -434 -435 >>> L[3, 5, 2].merge(operator.add, [-1, 4, -9]) -436 [2, 9, -7] -437 >>> list().merge(operator.sub, []) -438 [] -439 >>> L[3, 5, 2].merge(operator.add, [6]) -440 *- TypeError: the length of the two sequences must be equal -* -441 """ +@@ -2174,7 +2225,7 @@433 def merge( +434 self, +435 function: collections.abc.Callable[[_T, _U], _V], +436 other: collections.abc.Sequence[_U], +437 ) -> list[_V]: +438 """ +439 Build a new list from the result of each `function(s_i, o_i)` where +440 `s_i` and `o_i` are the items at index `i` of `self` and `other` +441 respectively. 442 -443 if len(self) != len(other): -444 raise TypeError("the length of the two sequences must be equal") -445 -446 return typing.cast( -447 list[_V], -448 self.__class__(function(a, b) for a, b in zip(self, other)), -449 ) +443 .. warning:: The list and the sequence must have the same length. +444 +445 >>> L[3, 5, 2].merge(operator.add, [-1, 4, -9]) +446 [2, 9, -7] +447 >>> list().merge(operator.sub, []) +448 [] +449 >>> L[3, 5, 2].merge(operator.add, [6]) +450 *- TypeError: the length of the two sequences must be equal -* +451 """ +452 +453 if len(self) != len(other): +454 msg = "the length of the two sequences must be equal" +455 raise TypeError(msg) +456 +457 return typing.cast( +458 list[_V], +459 self.__class__(function(a, b) for a, b in zip(self, other)), +460 )The list and the se
- + def flatten( self, *, _base: list[typing.Any] | None = None) -> list[typing.Any]: @@ -2182,49 +2233,49 @@-The list and the se
451 def flatten(self, *, _base: list[typing.Any] | None = None) -> list[typing.Any]: -452 """ -453 Flatten the contents to a 1-dimension list. If the list contains -454 itself, it cannot be flattened and a `ValueError` is raised. -455 -456 .. warning:: The list cannot contain recursive elements. -457 -458 >>> L[[3, 5, 2], [8, 4, 1], [7, 6, 9]].flatten() -459 [3, 5, 2, 8, 4, 1, 7, 6, 9] -460 >>> list().flatten() -461 [] -462 >>> l = list() -463 >>> l.append(l) -464 >>> l.flatten() -465 *- ValueError: cannot flatten list because it contains recursive elements -* -466 """ -467 -468 err = ValueError("cannot flatten list because it contains recursive elements") -469 -470 result: list[typing.Any] = list() -471 -472 for item in self: -473 if item is self or item is _base: -474 raise err -475 -476 base = self if _base is None else _base -477 -478 if isinstance(item, list): -479 result.extend(item.flatten(_base=base)) -480 elif isinstance(item, collections.abc.Iterable): -481 try: -482 result.extend( -483 list( -484 typing.cast(collections.abc.Iterable[typing.Any], item), -485 ).flatten(_base=base), -486 ) -487 except RecursionError: -488 # a bit dirty but I can't think of any other solution 😅 -489 raise err from None -490 else: -491 result.append(item) -492 -493 return result +@@ -2255,7 +2306,7 @@462 def flatten(self, *, _base: list[typing.Any] | None = None) -> list[typing.Any]: +463 """ +464 Flatten the contents to a 1-dimension list. If the list contains +465 itself, it cannot be flattened and a `ValueError` is raised. +466 +467 .. warning:: The list cannot contain recursive elements. +468 +469 >>> L[[3, 5, 2], [8, 4, 1], [7, 6, 9]].flatten() +470 [3, 5, 2, 8, 4, 1, 7, 6, 9] +471 >>> list().flatten() +472 [] +473 >>> l = list() +474 >>> l.append(l) +475 >>> l.flatten() +476 *- ValueError: cannot flatten list because it contains recursive elements -* +477 """ +478 +479 err = ValueError("cannot flatten list because it contains recursive elements") +480 +481 result: list[typing.Any] = list() +482 +483 for item in self: +484 if item is self or item is _base: +485 raise err +486 +487 base = self if _base is None else _base +488 +489 if isinstance(item, list): +490 result.extend(item.flatten(_base=base)) +491 elif isinstance(item, collections.abc.Iterable): +492 try: +493 result.extend( +494 list( +495 typing.cast(collections.abc.Iterable[typing.Any], item), +496 ).flatten(_base=base), +497 ) +498 except RecursionError: +499 # a bit dirty but I can't think of any other solution 😅 +500 raise err from None +501 else: +502 result.append(item) +503 +504 return resultThe list cannot contain recu
- + def sum(self) -> ~_T: @@ -2263,25 +2314,27 @@-The list cannot contain recu
495 def sum(self) -> _T: -496 """ -497 Return the sum of the list. The elements must support addition, -498 otherwise an exception is raised. -499 -500 .. warning:: The list must contain values that support the `+` operator, and be non-empty. -501 -502 >>> L[3, 5, 2].sum() -503 10 -504 >>> L["hello", "world"].sum() -505 "helloworld" -506 >>> list().sum() -507 *- TypeError: cannot perform summation on an empty list -* -508 """ -509 -510 if not self: -511 raise TypeError("cannot perform summation on an empty list") -512 -513 return self.reduce(operator.add) +@@ -2290,7 +2343,7 @@506 def sum(self) -> _T: +507 """ +508 Return the sum of the list. The elements must support addition, +509 otherwise an exception is raised. +510 +511 .. warning:: The list must contain values that support the `+` \ +512 operator, and be non-empty. +513 +514 >>> L[3, 5, 2].sum() +515 10 +516 >>> L["hello", "world"].sum() +517 "helloworld" +518 >>> list().sum() +519 *- TypeError: cannot perform summation on an empty list -* +520 """ +521 +522 if not self: +523 msg = "cannot perform summation on an empty list" +524 raise TypeError(msg) +525 +526 return self.reduce(operator.add)The list cannot contain recu
-@@ -2310,7 +2363,7 @@The list must contain values that support the
++
operator, and be non-empty.The list must contain values that support the
+
operator, and be non-empty.
- + def mean( self: list[int] | list[float] | list[complex]) -> float | complex: @@ -2318,29 +2371,31 @@-
515 def mean(self: list[int] | list[float] | list[complex]) -> float | complex: -516 """ -517 Return the mean of the list. The elements must be numbers. -518 -519 .. warning:: The list must contain numbers and be non-empty. -520 -521 >>> L[3, 5, 2].mean() -522 3.3333333333333335 -523 >>> L["hello", "world"].mean() -524 *- TypeError: cannot calculate mean of list of str -* -525 >>> list().mean() -526 *- TypeError: cannot calculate mean of empty list -* -527 """ -528 -529 if not self: -530 raise TypeError("cannot calculate mean of empty list") +@@ -2368,7 +2423,7 @@528 def mean(self: list[int] | list[float] | list[complex]) -> float | complex: +529 """ +530 Return the mean of the list. The elements must be numbers. 531 -532 if not hasattr(self[0], "__truediv__"): -533 raise TypeError( -534 f"cannot calculate mean of list of {self[0].__class__.__name__}", -535 ) -536 -537 return sum(self) / len(self) +532 .. warning:: The list must contain numbers and be non-empty. +533 +534 >>> L[3, 5, 2].mean() +535 3.3333333333333335 +536 >>> L["hello", "world"].mean() +537 *- TypeError: cannot calculate mean of list of str -* +538 >>> list().mean() +539 *- TypeError: cannot calculate mean of empty list -* +540 """ +541 +542 if not self: +543 msg = "cannot calculate mean of empty list" +544 raise TypeError(msg) +545 +546 if not hasattr(self[0], "__truediv__"): +547 msg = f"cannot calculate mean of list of {self[0].__class__.__name__}" +548 raise TypeError( +549 msg, +550 ) +551 +552 return sum(self) / len(self)The list must contain nu
- + def min( self: list[int] | list[float]) -> int | float: @@ -2376,27 +2431,29 @@-The list must contain nu
539 def min(self: list[int] | list[float]) -> int | float: -540 """ -541 Return the minimum value of the list. -542 -543 .. warning:: The list must be non-empty and contain numbers. -544 -545 >>> L[3, 5, 2].min() -546 2 -547 >>> L["hello", "world"].min() -548 *- TypeError: list of str has no minimum -* -549 >>> list().min() -550 *- TypeError: empty list has no minimum -* -551 """ -552 -553 if not self: -554 raise TypeError("empty list has no minimum") -555 -556 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] -557 raise TypeError(f"list of {type(self.head).__name__} has no minimum") -558 -559 return min(self) +@@ -2424,7 +2481,7 @@554 def min(self: list[int] | list[float]) -> int | float: +555 """ +556 Return the minimum value of the list. +557 +558 .. warning:: The list must be non-empty and contain numbers. +559 +560 >>> L[3, 5, 2].min() +561 2 +562 >>> L["hello", "world"].min() +563 *- TypeError: list of str has no minimum -* +564 >>> list().min() +565 *- TypeError: empty list has no minimum -* +566 """ +567 +568 if not self: +569 msg = "empty list has no minimum" +570 raise TypeError(msg) +571 +572 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] +573 msg = f"list of {type(self.head).__name__} has no minimum" +574 raise TypeError(msg) +575 +576 return min(self)The list must be non-emp
- + def max( self: list[int] | list[float]) -> int | float: @@ -2432,27 +2489,29 @@-The list must be non-emp
561 def max(self: list[int] | list[float]) -> int | float: -562 """ -563 Return the maximum value of the list. -564 -565 .. warning:: The list must be non-empty and contain numbers. -566 -567 >>> L[3, 5, 2].max() -568 2 -569 >>> L["hello", "world"].max() -570 *- TypeError: list of str has no maximum -* -571 >>> list().max() -572 *- TypeError: empty list has no maximum -* -573 """ -574 -575 if not self: -576 raise TypeError("empty list has no maximum") -577 -578 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] -579 raise TypeError(f"list of {type(self.head).__name__} has no maximum") -580 -581 return max(self) +@@ -2480,7 +2539,7 @@578 def max(self: list[int] | list[float]) -> int | float: +579 """ +580 Return the maximum value of the list. +581 +582 .. warning:: The list must be non-empty and contain numbers. +583 +584 >>> L[3, 5, 2].max() +585 2 +586 >>> L["hello", "world"].max() +587 *- TypeError: list of str has no maximum -* +588 >>> list().max() +589 *- TypeError: empty list has no maximum -* +590 """ +591 +592 if not self: +593 msg = "empty list has no maximum" +594 raise TypeError(msg) +595 +596 if not isinstance(self.head, (int, float)): # pyright: ignore[reportUnnecessaryIsInstance] +597 msg = f"list of {type(self.head).__name__} has no maximum" +598 raise TypeError(msg) +599 +600 return max(self)The list must be non-emp
- + def fill_left( self, filler: Union[~_T, collections.abc.Callable[[list[~_T]], ~_T]], n: int) -> Self: @@ -2488,38 +2547,39 @@-The list must be non-emp
583 def fill_left( -584 self, -585 filler: _T | collections.abc.Callable[[list[_T]], _T], -586 n: int, -587 ) -> typing_extensions.Self: -588 """ -589 Fill on the left the list with `filler` and return the result. -590 -591 If `filler` is a function, it takes the current list (at the current -592 filling iteration) and produces a new value to be appended. -593 -594 .. warning:: `n` must be non-negative. -595 -596 >>> L[3, 5, 2].fill_left(0, 5) -597 [0, 0, 0, 0, 0, 3, 5, 2] -598 >>> L[3, 5, 2].fill_left(sum, 3) -599 [40, 20, 10, 3, 5, 2] -600 >>> list().fill_left(1, 10) -601 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] -602 >>> L[3, 5, 2].fill_left(0, -1) -603 *- ValueError: the number of times to fill cannot be negative -* -604 """ -605 -606 if n < 0: -607 raise ValueError("the number of times to fill cannot be negative") -608 -609 returned_list = self.copy() -610 -611 for _ in range(n): -612 returned_list.prepend(filler(returned_list) if callable(filler) else filler) -613 -614 return returned_list +@@ -2552,7 +2612,7 @@602 def fill_left( +603 self, +604 filler: _T | collections.abc.Callable[[list[_T]], _T], +605 n: int, +606 ) -> typing_extensions.Self: +607 """ +608 Fill on the left the list with `filler` and return the result. +609 +610 If `filler` is a function, it takes the current list (at the current +611 filling iteration) and produces a new value to be appended. +612 +613 .. warning:: `n` must be non-negative. +614 +615 >>> L[3, 5, 2].fill_left(0, 5) +616 [0, 0, 0, 0, 0, 3, 5, 2] +617 >>> L[3, 5, 2].fill_left(sum, 3) +618 [40, 20, 10, 3, 5, 2] +619 >>> list().fill_left(1, 10) +620 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +621 >>> L[3, 5, 2].fill_left(0, -1) +622 *- ValueError: the number of times to fill cannot be negative -* +623 """ +624 +625 if n < 0: +626 msg = "the number of times to fill cannot be negative" +627 raise ValueError(msg) +628 +629 returned_list = self.copy() +630 +631 for _ in range(n): +632 returned_list.prepend(filler(returned_list) if callable(filler) else filler) +633 +634 return returned_list
n
must be non-negative.- + def fill_right( self, filler: Union[~_T, collections.abc.Callable[[list[~_T]], ~_T]], n: int) -> Self: @@ -2560,38 +2620,39 @@-
n
must be non-negative.616 def fill_right( -617 self, -618 filler: _T | collections.abc.Callable[[list[_T]], _T], -619 n: int, -620 ) -> typing_extensions.Self: -621 """ -622 Fill on the right the list with `filler` and return the result. -623 -624 If `filler` is a function, it takes the current list (at the current -625 filling iteration) and produces a new value to be appended. -626 -627 .. warning:: `n` must be non-negative. -628 -629 >>> L[3, 5, 2].fill_right(0, 5) -630 [3, 5, 2, 0, 0, 0, 0, 0] -631 >>> L[3, 5, 2].fill_right(sum, 3) -632 [3, 5, 2, 10, 20, 40] -633 >>> list().fill_right(1, 10) -634 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] -635 >>> L[3, 5, 2].fill_right(0, -1) -636 *- ValueError: the number of times to fill cannot be negative -* -637 """ -638 -639 if n < 0: -640 raise ValueError("the number of times to fill cannot be negative") -641 -642 returned_list = self.copy() +@@ -2624,7 +2685,7 @@636 def fill_right( +637 self, +638 filler: _T | collections.abc.Callable[[list[_T]], _T], +639 n: int, +640 ) -> typing_extensions.Self: +641 """ +642 Fill on the right the list with `filler` and return the result. 643 -644 for _ in range(n): -645 returned_list.append(filler(returned_list) if callable(filler) else filler) +644 If `filler` is a function, it takes the current list (at the current +645 filling iteration) and produces a new value to be appended. 646 -647 return returned_list +647 .. warning:: `n` must be non-negative. +648 +649 >>> L[3, 5, 2].fill_right(0, 5) +650 [3, 5, 2, 0, 0, 0, 0, 0] +651 >>> L[3, 5, 2].fill_right(sum, 3) +652 [3, 5, 2, 10, 20, 40] +653 >>> list().fill_right(1, 10) +654 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] +655 >>> L[3, 5, 2].fill_right(0, -1) +656 *- ValueError: the number of times to fill cannot be negative -* +657 """ +658 +659 if n < 0: +660 msg = "the number of times to fill cannot be negative" +661 raise ValueError(msg) +662 +663 returned_list = self.copy() +664 +665 for _ in range(n): +666 returned_list.append(filler(returned_list) if callable(filler) else filler) +667 +668 return returned_list
n
must be non-negative.- + def interleave( self, filler: Union[~_T, collections.abc.Callable[[~_T, ~_T], ~_T]]) -> Self: @@ -2632,40 +2693,41 @@-
n
must be non-negative.649 def interleave( -650 self, -651 filler: _T | collections.abc.Callable[[_T, _T], _T], -652 ) -> typing_extensions.Self: -653 """ -654 Fill in-between the items with `filler` and return the result. -655 -656 If `filler` is a function, it takes the two items surrounding the gap -657 that is about to be filled and produces a new value to be inserted. -658 -659 .. warning:: The list must contain at least two items. -660 -661 >>> L[3, 5, 2].interleave(0) -662 [3, 0, 5, 0, 2] -663 >>> L[3, 5, 2].interleave(operator.add) -664 [3, 8, 5, 7, 2] -665 >>> L[0].interleave(1) -666 *- ValueError: list has no gap to be filled -* -667 >>> list().interleave(0) -668 *- ValueError: list has no gap to be filled -* -669 """ -670 -671 if len(self) <= 1: -672 raise ValueError("list has no gap to be filled") -673 -674 returned_list = self.__class__([self.head]) -675 -676 for i in range(1, len(self)): -677 returned_list.append( -678 filler(self[i - 1], self[i]) if callable(filler) else filler, -679 ) -680 returned_list.append(self[i]) +@@ -2698,7 +2760,7 @@670 def interleave( +671 self, +672 filler: _T | collections.abc.Callable[[_T, _T], _T], +673 ) -> typing_extensions.Self: +674 """ +675 Fill in-between the items with `filler` and return the result. +676 +677 If `filler` is a function, it takes the two items surrounding the gap +678 that is about to be filled and produces a new value to be inserted. +679 +680 .. warning:: The list must contain at least two items. 681 -682 return returned_list +682 >>> L[3, 5, 2].interleave(0) +683 [3, 0, 5, 0, 2] +684 >>> L[3, 5, 2].interleave(operator.add) +685 [3, 8, 5, 7, 2] +686 >>> L[0].interleave(1) +687 *- ValueError: list has no gap to be filled -* +688 >>> list().interleave(0) +689 *- ValueError: list has no gap to be filled -* +690 """ +691 +692 if len(self) <= 1: +693 msg = "list has no gap to be filled" +694 raise ValueError(msg) +695 +696 returned_list = self.__class__([self.head]) +697 +698 for i in range(1, len(self)): +699 returned_list.append( +700 filler(self[i - 1], self[i]) if callable(filler) else filler, +701 ) +702 returned_list.append(self[i]) +703 +704 return returned_listThe list must contain at least
- + def gap_fill( self, filler: Union[~_T, collections.abc.Callable[[~_T, ~_T], ~_T]]) -> Self: @@ -2706,40 +2768,41 @@-The list must contain at least
649 def interleave( -650 self, -651 filler: _T | collections.abc.Callable[[_T, _T], _T], -652 ) -> typing_extensions.Self: -653 """ -654 Fill in-between the items with `filler` and return the result. -655 -656 If `filler` is a function, it takes the two items surrounding the gap -657 that is about to be filled and produces a new value to be inserted. -658 -659 .. warning:: The list must contain at least two items. -660 -661 >>> L[3, 5, 2].interleave(0) -662 [3, 0, 5, 0, 2] -663 >>> L[3, 5, 2].interleave(operator.add) -664 [3, 8, 5, 7, 2] -665 >>> L[0].interleave(1) -666 *- ValueError: list has no gap to be filled -* -667 >>> list().interleave(0) -668 *- ValueError: list has no gap to be filled -* -669 """ -670 -671 if len(self) <= 1: -672 raise ValueError("list has no gap to be filled") -673 -674 returned_list = self.__class__([self.head]) -675 -676 for i in range(1, len(self)): -677 returned_list.append( -678 filler(self[i - 1], self[i]) if callable(filler) else filler, -679 ) -680 returned_list.append(self[i]) +@@ -2757,7 +2820,7 @@670 def interleave( +671 self, +672 filler: _T | collections.abc.Callable[[_T, _T], _T], +673 ) -> typing_extensions.Self: +674 """ +675 Fill in-between the items with `filler` and return the result. +676 +677 If `filler` is a function, it takes the two items surrounding the gap +678 that is about to be filled and produces a new value to be inserted. +679 +680 .. warning:: The list must contain at least two items. 681 -682 return returned_list +682 >>> L[3, 5, 2].interleave(0) +683 [3, 0, 5, 0, 2] +684 >>> L[3, 5, 2].interleave(operator.add) +685 [3, 8, 5, 7, 2] +686 >>> L[0].interleave(1) +687 *- ValueError: list has no gap to be filled -* +688 >>> list().interleave(0) +689 *- ValueError: list has no gap to be filled -* +690 """ +691 +692 if len(self) <= 1: +693 msg = "list has no gap to be filled" +694 raise ValueError(msg) +695 +696 returned_list = self.__class__([self.head]) +697 +698 for i in range(1, len(self)): +699 returned_list.append( +700 filler(self[i - 1], self[i]) if callable(filler) else filler, +701 ) +702 returned_list.append(self[i]) +703 +704 return returned_listThis alias is deprecated.
- + def select(self, indexes: collections.abc.Sequence[int]) -> Self: @@ -2765,33 +2828,34 @@-This alias is deprecated.
691 def select( -692 self, -693 indexes: collections.abc.Sequence[int], -694 ) -> typing_extensions.Self: -695 """ -696 Select items at provided indexes. If an index is present several -697 times, this will be reflected in the resulting list. -698 -699 .. warning:: All the indexes must be in bounds. -700 -701 >>> L[3, 5, 2].select([1, 2, 0, 0]) -702 [5, 2, 3, 3] -703 >>> list().select([]) -704 [] -705 >>> L[3, 5, 2].select([4, 1]) -706 *- IndexError: index 4 is out of bounds -* -707 """ -708 -709 returned_list = self.__class__() -710 -711 for index in indexes: -712 if index >= len(self) or index < -len(self): -713 raise IndexError(f"index {index} is out of bounds") -714 -715 returned_list.append(self[index]) -716 -717 return returned_list +@@ -2820,7 +2884,7 @@713 def select( +714 self, +715 indexes: collections.abc.Sequence[int], +716 ) -> typing_extensions.Self: +717 """ +718 Select items at provided indexes. If an index is present several +719 times, this will be reflected in the resulting list. +720 +721 .. warning:: All the indexes must be in bounds. +722 +723 >>> L[3, 5, 2].select([1, 2, 0, 0]) +724 [5, 2, 3, 3] +725 >>> list().select([]) +726 [] +727 >>> L[3, 5, 2].select([4, 1]) +728 *- IndexError: index 4 is out of bounds -* +729 """ +730 +731 returned_list = self.__class__() +732 +733 for index in indexes: +734 if index >= len(self) or index < -len(self): +735 msg = f"index {index} is out of bounds" +736 raise IndexError(msg) +737 +738 returned_list.append(self[index]) +739 +740 return returned_listAll the indexes must be in bounds.
- + def take(self, n: int) -> Self: @@ -2828,29 +2892,31 @@All the indexes must be in bounds. -
719 def take(self, n: int) -> typing_extensions.Self: -720 """ -721 Take `n` items from the list and return them. -722 -723 .. warning:: `n` must be non-negative and less than the list length. -724 -725 >>> L[3, 5, 2].take(2) -726 [3, 5] -727 >>> L[3, 5, 2].take(0) -728 [] -729 >>> L[3, 5, 2].take(-1) -730 *- ValueError: cannot take a negative amount of items -* -731 >>> L[3, 5, 2].take(5) -732 *- ValueError: cannot take more items than the list contains -* -733 """ -734 -735 if n < 0: -736 raise ValueError("cannot take a negative amount of items") -737 -738 if n > len(self): -739 raise ValueError("cannot take more items than the list contains") -740 -741 return self.__class__(self[i] for i in range(n)) +@@ -2880,7 +2946,7 @@742 def take(self, n: int) -> typing_extensions.Self: +743 """ +744 Take `n` items from the list and return them. +745 +746 .. warning:: `n` must be non-negative and less than the list length. +747 +748 >>> L[3, 5, 2].take(2) +749 [3, 5] +750 >>> L[3, 5, 2].take(0) +751 [] +752 >>> L[3, 5, 2].take(-1) +753 *- ValueError: cannot take a negative amount of items -* +754 >>> L[3, 5, 2].take(5) +755 *- ValueError: cannot take more items than the list contains -* +756 """ +757 +758 if n < 0: +759 msg = "cannot take a negative amount of items" +760 raise ValueError(msg) +761 +762 if n > len(self): +763 msg = "cannot take more items than the list contains" +764 raise ValueError(msg) +765 +766 return self.__class__(self[i] for i in range(n))
n
mus- + def take_right(self, n: int) -> Self: @@ -2888,31 +2954,33 @@-
n
mus743 def take_right(self, n: int) -> typing_extensions.Self: -744 """ -745 Take `n` items from the right of the list and return them. -746 -747 List original order is preserved. -748 -749 .. warning:: `n` must be non-negative and less than the list length. -750 -751 >>> L[3, 5, 2].take_right(2) -752 [5, 2] -753 >>> L[3, 5, 2].take_right(0) -754 [] -755 >>> L[3, 5, 2].take_right(-1) -756 *- ValueError: cannot take a negative amount of items -* -757 >>> L[3, 5, 2].take_right(5) -758 *- ValueError: cannot take more items than the list contains -* -759 """ -760 -761 if n < 0: -762 raise ValueError("cannot take a negative amount of items") -763 -764 if n > len(self): -765 raise ValueError("cannot take more items than the list contains") -766 -767 return self.__class__(item for item in self[len(self) - n :]) +@@ -2944,7 +3012,7 @@768 def take_right(self, n: int) -> typing_extensions.Self: +769 """ +770 Take `n` items from the right of the list and return them. +771 +772 List original order is preserved. +773 +774 .. warning:: `n` must be non-negative and less than the list length. +775 +776 >>> L[3, 5, 2].take_right(2) +777 [5, 2] +778 >>> L[3, 5, 2].take_right(0) +779 [] +780 >>> L[3, 5, 2].take_right(-1) +781 *- ValueError: cannot take a negative amount of items -* +782 >>> L[3, 5, 2].take_right(5) +783 *- ValueError: cannot take more items than the list contains -* +784 """ +785 +786 if n < 0: +787 msg = "cannot take a negative amount of items" +788 raise ValueError(msg) +789 +790 if n > len(self): +791 msg = "cannot take more items than the list contains" +792 raise ValueError(msg) +793 +794 return self.__class__(item for item in self[len(self) - n :])
n
mus- + def drop(self, n: int) -> Self: @@ -2952,29 +3020,31 @@-
n
mus769 def drop(self, n: int) -> typing_extensions.Self: -770 """ -771 Drop `n` items from the list and return the rest. -772 -773 .. warning:: `n` must be non-negative and less than the list length. -774 -775 >>> L[3, 5, 2].drop(2) -776 [2] -777 >>> L[3, 5, 2].drop(0) -778 [3, 5, 2] -779 >>> L[3, 5, 2].drop(-1) -780 *- ValueError: cannot drop a negative amount of items -* -781 >>> L[3, 5, 2].drop(5) -782 *- ValueError: cannot drop more items than the list contains -* -783 """ -784 -785 if n < 0: -786 raise ValueError("cannot drop a negative amount of items") -787 -788 if n > len(self): -789 raise ValueError("cannot drop more items than the list contains") -790 -791 return self.__class__(self[n:]) +@@ -3004,7 +3074,7 @@796 def drop(self, n: int) -> typing_extensions.Self: +797 """ +798 Drop `n` items from the list and return the rest. +799 +800 .. warning:: `n` must be non-negative and less than the list length. +801 +802 >>> L[3, 5, 2].drop(2) +803 [2] +804 >>> L[3, 5, 2].drop(0) +805 [3, 5, 2] +806 >>> L[3, 5, 2].drop(-1) +807 *- ValueError: cannot drop a negative amount of items -* +808 >>> L[3, 5, 2].drop(5) +809 *- ValueError: cannot drop more items than the list contains -* +810 """ +811 +812 if n < 0: +813 msg = "cannot drop a negative amount of items" +814 raise ValueError(msg) +815 +816 if n > len(self): +817 msg = "cannot drop more items than the list contains" +818 raise ValueError(msg) +819 +820 return self.__class__(self[n:])
n
mus- + def drop_right(self, n: int) -> Self: @@ -3012,29 +3082,31 @@-
n
mus793 def drop_right(self, n: int) -> typing_extensions.Self: -794 """ -795 Drop `n` items from the right of the list and return the rest. -796 -797 .. warning:: `n` must be non-negative and less than the list length. -798 -799 >>> L[3, 5, 2].drop_right(2) -800 [3] -801 >>> L[3, 5, 2].drop_right(0) -802 [3, 5, 2] -803 >>> L[3, 5, 2].drop_right(-1) -804 *- ValueError: cannot drop a negative amount of items -* -805 >>> L[3, 5, 2].drop_right(5) -806 *- ValueError: cannot drop more items than the list contains -* -807 """ -808 -809 if n < 0: -810 raise ValueError("cannot drop a negative amount of items") -811 -812 if n > len(self): -813 raise ValueError("cannot drop more items than the list contains") -814 -815 return self.__class__(self[: len(self) - n]) +@@ -3064,7 +3136,7 @@822 def drop_right(self, n: int) -> typing_extensions.Self: +823 """ +824 Drop `n` items from the right of the list and return the rest. +825 +826 .. warning:: `n` must be non-negative and less than the list length. +827 +828 >>> L[3, 5, 2].drop_right(2) +829 [3] +830 >>> L[3, 5, 2].drop_right(0) +831 [3, 5, 2] +832 >>> L[3, 5, 2].drop_right(-1) +833 *- ValueError: cannot drop a negative amount of items -* +834 >>> L[3, 5, 2].drop_right(5) +835 *- ValueError: cannot drop more items than the list contains -* +836 """ +837 +838 if n < 0: +839 msg = "cannot drop a negative amount of items" +840 raise ValueError(msg) +841 +842 if n > len(self): +843 msg = "cannot drop more items than the list contains" +844 raise ValueError(msg) +845 +846 return self.__class__(self[: len(self) - n])
n
mus- + def slice(self, start: int, stop: int) -> Self: @@ -3072,41 +3144,43 @@-
n
mus817 def slice(self, start: int, stop: int) -> typing_extensions.Self: -818 """ -819 Slice the list from `start` to `stop` and return the result. -820 -821 This method is NOT equivalent to the `self[start:stop]` notation. -822 If `start` or `stop` are out of bounds of the list or `start` is -823 greater than `stop`, it will raise an exception. -824 -825 .. warning:: `start` and `stop` must be in bounds. -826 -827 >>> L[2, 4, 8, 16, 32].slice(1, 3) -828 [4, 8, 16] -829 >>> L[2, 4, 8, 16, 32].slice(0, 2) -830 [2, 4, 8] -831 >>> L[2, 4, 8, 16, 32].slice(3, 5) -832 [8, 16, 32] -833 >>> L[2, 4, 8, 16, 32].slice(2, 2) -834 [8] -835 >>> L[2, 4, 8, 16, 32].slice(1, 10) -836 *- ValueError: slice out of bounds -* -837 >>> L[2, 4, 8, 16, 32].slice(4, 2) -838 *- ValueError: start cannot be greater than stop -* -839 -840 Tip: if `start` is 0, you can do `.take(stop - 1)` instead. -841 Symmetrically, if `stop` is the index of the last item, go for a -842 `.drop(start)`! -843 """ -844 -845 if start > stop: -846 raise ValueError("start cannot be greater than stop") -847 -848 if start < 0 or stop >= len(self): -849 raise ValueError("slice out of bounds") -850 -851 return self.__class__(self[start : stop + 1]) +@@ -3148,7 +3222,7 @@848 def slice(self, start: int, stop: int) -> typing_extensions.Self: +849 """ +850 Slice the list from `start` to `stop` and return the result. +851 +852 This method is NOT equivalent to the `self[start:stop]` notation. +853 If `start` or `stop` are out of bounds of the list or `start` is +854 greater than `stop`, it will raise an exception. +855 +856 .. warning:: `start` and `stop` must be in bounds. +857 +858 >>> L[2, 4, 8, 16, 32].slice(1, 3) +859 [4, 8, 16] +860 >>> L[2, 4, 8, 16, 32].slice(0, 2) +861 [2, 4, 8] +862 >>> L[2, 4, 8, 16, 32].slice(3, 5) +863 [8, 16, 32] +864 >>> L[2, 4, 8, 16, 32].slice(2, 2) +865 [8] +866 >>> L[2, 4, 8, 16, 32].slice(1, 10) +867 *- ValueError: slice out of bounds -* +868 >>> L[2, 4, 8, 16, 32].slice(4, 2) +869 *- ValueError: start cannot be greater than stop -* +870 +871 Tip: if `start` is 0, you can do `.take(stop - 1)` instead. +872 Symmetrically, if `stop` is the index of the last item, go for a +873 `.drop(start)`! +874 """ +875 +876 if start > stop: +877 msg = "start cannot be greater than stop" +878 raise ValueError(msg) +879 +880 if start < 0 or stop >= len(self): +881 msg = "slice out of bounds" +882 raise ValueError(msg) +883 +884 return self.__class__(self[start : stop + 1])
start
andstop
- + def partition(self, index: int) -> tuple[typing.Self, ~_T, typing.Self]: @@ -3156,35 +3230,37 @@
start
andstop -
853 def partition( -854 self, -855 index: int, -856 ) -> tuple[typing_extensions.Self, _T, typing_extensions.Self]: -857 """ -858 Return the item at index `index`, but also the two list slices -859 before and after that item, in this order: (left, item, right). -860 -861 .. warning:: The list must be non-empty, and the partition index in bounds. -862 -863 >>> L[2, 4, 8, 16, 32].partition(2) -864 ([2, 4], 8, [16, 32]) -865 >>> L[2, 4, 8, 16, 32].partition(0) -866 ([], 2, [4, 8, 16, 32]) -867 >>> L[2, 4, 8, 16, 32].partition(4) -868 ([2, 4, 8, 16], 32, []) -869 >>> L[2, 4, 8, 16, 32].partition(-2) -870 *- IndexError: partition index cannot be out of bounds -* -871 >>> list().partition(2) -872 *- TypeError: cannot partition an empty list -* -873 """ -874 -875 if not self: -876 raise TypeError("cannot partition an empty list") -877 -878 if not (0 <= index < len(self)): -879 raise IndexError("partition index cannot be out of bounds") -880 -881 return self.take(index), self[index], self.drop(index + 1) +@@ -3217,7 +3293,7 @@886 def partition( +887 self, +888 index: int, +889 ) -> tuple[typing_extensions.Self, _T, typing_extensions.Self]: +890 """ +891 Return the item at index `index`, but also the two list slices +892 before and after that item, in this order: (left, item, right). +893 +894 .. warning:: The list must be non-empty, and the partition index in bounds. +895 +896 >>> L[2, 4, 8, 16, 32].partition(2) +897 ([2, 4], 8, [16, 32]) +898 >>> L[2, 4, 8, 16, 32].partition(0) +899 ([], 2, [4, 8, 16, 32]) +900 >>> L[2, 4, 8, 16, 32].partition(4) +901 ([2, 4, 8, 16], 32, []) +902 >>> L[2, 4, 8, 16, 32].partition(-2) +903 *- IndexError: partition index cannot be out of bounds -* +904 >>> list().partition(2) +905 *- TypeError: cannot partition an empty list -* +906 """ +907 +908 if not self: +909 msg = "cannot partition an empty list" +910 raise TypeError(msg) +911 +912 if not (0 <= index < len(self)): +913 msg = "partition index cannot be out of bounds" +914 raise IndexError(msg) +915 +916 return self.take(index), self[index], self.drop(index + 1)The list m
- + def bisect(self, index: int) -> tuple[typing.Self, typing.Self]: @@ -3225,34 +3301,35 @@-The list m
883 def bisect( -884 self, -885 index: int, -886 ) -> tuple[typing_extensions.Self, typing_extensions.Self]: -887 """ -888 Bisect the list after `index` elements and return a pair of the produced -889 lists. -890 -891 .. warning:: The list must be non-empty. -892 -893 >>> L[2, 4, 8, 16, 32].bisect(2) -894 ([2, 4], [8, 16, 32]) -895 >>> L[2, 4, 8, 16, 32].bisect(0) -896 ([], [2, 4, 8, 16, 32]) -897 >>> L[2, 4, 8, 16, 32].bisect(8) -898 ([2, 4, 8, 16, 32], []) -899 >>> L[2, 4, 8, 16, 32].bisect(-3) -900 ([], [2, 4, 8, 16, 32]) -901 >>> list().bisect(2) -902 *- TypeError: cannot bisect an empty list -* -903 """ -904 -905 if not self: -906 raise TypeError("cannot bisect an empty list") -907 -908 _n = _minmax(index, 0, len(self)) -909 -910 return self.take(_n), self.drop(_n) +@@ -3285,7 +3362,7 @@918 def bisect( +919 self, +920 index: int, +921 ) -> tuple[typing_extensions.Self, typing_extensions.Self]: +922 """ +923 Bisect the list after `index` elements and return a pair of the produced +924 lists. +925 +926 .. warning:: The list must be non-empty. +927 +928 >>> L[2, 4, 8, 16, 32].bisect(2) +929 ([2, 4], [8, 16, 32]) +930 >>> L[2, 4, 8, 16, 32].bisect(0) +931 ([], [2, 4, 8, 16, 32]) +932 >>> L[2, 4, 8, 16, 32].bisect(8) +933 ([2, 4, 8, 16, 32], []) +934 >>> L[2, 4, 8, 16, 32].bisect(-3) +935 ([], [2, 4, 8, 16, 32]) +936 >>> list().bisect(2) +937 *- TypeError: cannot bisect an empty list -* +938 """ +939 +940 if not self: +941 msg = "cannot bisect an empty list" +942 raise TypeError(msg) +943 +944 _n = _minmax(index, 0, len(self)) +945 +946 return self.take(_n), self.drop(_n)The list must be non-empty.
- + def trisect( self, first_index: int, second_index: int) -> tuple[typing.Self, typing.Self, typing.Self]: @@ -3293,33 +3370,34 @@-The list must be non-empty.
- - + +912 def trisect( -913 self, -914 first_index: int, -915 second_index: int, -916 ) -> tuple[ -917 typing_extensions.Self, -918 typing_extensions.Self, -919 typing_extensions.Self, -920 ]: -921 """ -922 Trisect the list at `first_index` and `second_index` and return a -923 triple of the produced lists. -924 -925 The left and right cutting indexes are determined by the smallest and -926 largest value of the two arguments respectively ; `first_index` is not -927 required to be smaller. -928 -929 .. warning:: The list must be non-empty. -930 """ -931 -932 if not self: -933 raise TypeError("cannot trisect an empty list") -934 -935 _left = _minmax(min(first_index, second_index), 0, len(self)) -936 _right = _minmax(max(first_index, second_index), 0, len(self)) -937 -938 return self.take(_left), self[_left:_right], self.drop(_right) +@@ -3366,13 +3444,13 @@948 def trisect( +949 self, +950 first_index: int, +951 second_index: int, +952 ) -> tuple[ +953 typing_extensions.Self, +954 typing_extensions.Self, +955 typing_extensions.Self, +956 ]: +957 """ +958 Trisect the list at `first_index` and `second_index` and return a +959 triple of the produced lists. +960 +961 The left and right cutting indexes are determined by the smallest and +962 largest value of the two arguments respectively ; `first_index` is not +963 required to be smaller. +964 +965 .. warning:: The list must be non-empty. +966 """ +967 +968 if not self: +969 msg = "cannot trisect an empty list" +970 raise TypeError(msg) +971 +972 _left = _minmax(min(first_index, second_index), 0, len(self)) +973 _right = _minmax(max(first_index, second_index), 0, len(self)) +974 +975 return self.take(_left), self[_left:_right], self.drop(_right)Inherited Members
L = <magic_list.prelude._ListBuilder object> - +