1# Copyright 2007 Google, Inc. All Rights Reserved. 2# Licensed to PSF under a Contributor Agreement. 3 4"""Abstract Base Classes (ABCs) for collections, according to PEP 3119. 5 6Unit tests are in test_collections. 7""" 8 9from abc import ABCMeta, abstractmethod 10import sys 11 12GenericAlias = type(list[int]) 13 14__all__ = ["Awaitable", "Coroutine", 15 "AsyncIterable", "AsyncIterator", "AsyncGenerator", 16 "Hashable", "Iterable", "Iterator", "Generator", "Reversible", 17 "Sized", "Container", "Callable", "Collection", 18 "Set", "MutableSet", 19 "Mapping", "MutableMapping", 20 "MappingView", "KeysView", "ItemsView", "ValuesView", 21 "Sequence", "MutableSequence", 22 "ByteString", 23 ] 24 25# This module has been renamed from collections.abc to _collections_abc to 26# speed up interpreter startup. Some of the types such as MutableMapping are 27# required early but collections module imports a lot of other modules. 28# See issue #19218 29__name__ = "collections.abc" 30 31# Private list of types that we want to register with the various ABCs 32# so that they will pass tests like: 33# it = iter(somebytearray) 34# assert isinstance(it, Iterable) 35# Note: in other implementations, these types might not be distinct 36# and they may have their own implementation specific types that 37# are not included on this list. 38bytes_iterator = type(iter(b'')) 39bytearray_iterator = type(iter(bytearray())) 40#callable_iterator = ??? 41dict_keyiterator = type(iter({}.keys())) 42dict_valueiterator = type(iter({}.values())) 43dict_itemiterator = type(iter({}.items())) 44list_iterator = type(iter([])) 45list_reverseiterator = type(iter(reversed([]))) 46range_iterator = type(iter(range(0))) 47longrange_iterator = type(iter(range(1 << 1000))) 48set_iterator = type(iter(set())) 49str_iterator = type(iter("")) 50tuple_iterator = type(iter(())) 51zip_iterator = type(iter(zip())) 52## views ## 53dict_keys = type({}.keys()) 54dict_values = type({}.values()) 55dict_items = type({}.items()) 56## misc ## 57mappingproxy = type(type.__dict__) 58generator = type((lambda: (yield))()) 59## coroutine ## 60async def _coro(): pass 61_coro = _coro() 62coroutine = type(_coro) 63_coro.close() # Prevent ResourceWarning 64del _coro 65## asynchronous generator ## 66async def _ag(): yield 67_ag = _ag() 68async_generator = type(_ag) 69del _ag 70 71 72### ONE-TRICK PONIES ### 73 74def _check_methods(C, *methods): 75 mro = C.__mro__ 76 for method in methods: 77 for B in mro: 78 if method in B.__dict__: 79 if B.__dict__[method] is None: 80 return NotImplemented 81 break 82 else: 83 return NotImplemented 84 return True 85 86class Hashable(metaclass=ABCMeta): 87 88 __slots__ = () 89 90 @abstractmethod 91 def __hash__(self): 92 return 0 93 94 @classmethod 95 def __subclasshook__(cls, C): 96 if cls is Hashable: 97 return _check_methods(C, "__hash__") 98 return NotImplemented 99 100 101class Awaitable(metaclass=ABCMeta): 102 103 __slots__ = () 104 105 @abstractmethod 106 def __await__(self): 107 yield 108 109 @classmethod 110 def __subclasshook__(cls, C): 111 if cls is Awaitable: 112 return _check_methods(C, "__await__") 113 return NotImplemented 114 115 __class_getitem__ = classmethod(GenericAlias) 116 117 118class Coroutine(Awaitable): 119 120 __slots__ = () 121 122 @abstractmethod 123 def send(self, value): 124 """Send a value into the coroutine. 125 Return next yielded value or raise StopIteration. 126 """ 127 raise StopIteration 128 129 @abstractmethod 130 def throw(self, typ, val=None, tb=None): 131 """Raise an exception in the coroutine. 132 Return next yielded value or raise StopIteration. 133 """ 134 if val is None: 135 if tb is None: 136 raise typ 137 val = typ() 138 if tb is not None: 139 val = val.with_traceback(tb) 140 raise val 141 142 def close(self): 143 """Raise GeneratorExit inside coroutine. 144 """ 145 try: 146 self.throw(GeneratorExit) 147 except (GeneratorExit, StopIteration): 148 pass 149 else: 150 raise RuntimeError("coroutine ignored GeneratorExit") 151 152 @classmethod 153 def __subclasshook__(cls, C): 154 if cls is Coroutine: 155 return _check_methods(C, '__await__', 'send', 'throw', 'close') 156 return NotImplemented 157 158 159Coroutine.register(coroutine) 160 161 162class AsyncIterable(metaclass=ABCMeta): 163 164 __slots__ = () 165 166 @abstractmethod 167 def __aiter__(self): 168 return AsyncIterator() 169 170 @classmethod 171 def __subclasshook__(cls, C): 172 if cls is AsyncIterable: 173 return _check_methods(C, "__aiter__") 174 return NotImplemented 175 176 __class_getitem__ = classmethod(GenericAlias) 177 178 179class AsyncIterator(AsyncIterable): 180 181 __slots__ = () 182 183 @abstractmethod 184 async def __anext__(self): 185 """Return the next item or raise StopAsyncIteration when exhausted.""" 186 raise StopAsyncIteration 187 188 def __aiter__(self): 189 return self 190 191 @classmethod 192 def __subclasshook__(cls, C): 193 if cls is AsyncIterator: 194 return _check_methods(C, "__anext__", "__aiter__") 195 return NotImplemented 196 197 198class AsyncGenerator(AsyncIterator): 199 200 __slots__ = () 201 202 async def __anext__(self): 203 """Return the next item from the asynchronous generator. 204 When exhausted, raise StopAsyncIteration. 205 """ 206 return await self.asend(None) 207 208 @abstractmethod 209 async def asend(self, value): 210 """Send a value into the asynchronous generator. 211 Return next yielded value or raise StopAsyncIteration. 212 """ 213 raise StopAsyncIteration 214 215 @abstractmethod 216 async def athrow(self, typ, val=None, tb=None): 217 """Raise an exception in the asynchronous generator. 218 Return next yielded value or raise StopAsyncIteration. 219 """ 220 if val is None: 221 if tb is None: 222 raise typ 223 val = typ() 224 if tb is not None: 225 val = val.with_traceback(tb) 226 raise val 227 228 async def aclose(self): 229 """Raise GeneratorExit inside coroutine. 230 """ 231 try: 232 await self.athrow(GeneratorExit) 233 except (GeneratorExit, StopAsyncIteration): 234 pass 235 else: 236 raise RuntimeError("asynchronous generator ignored GeneratorExit") 237 238 @classmethod 239 def __subclasshook__(cls, C): 240 if cls is AsyncGenerator: 241 return _check_methods(C, '__aiter__', '__anext__', 242 'asend', 'athrow', 'aclose') 243 return NotImplemented 244 245 246AsyncGenerator.register(async_generator) 247 248 249class Iterable(metaclass=ABCMeta): 250 251 __slots__ = () 252 253 @abstractmethod 254 def __iter__(self): 255 while False: 256 yield None 257 258 @classmethod 259 def __subclasshook__(cls, C): 260 if cls is Iterable: 261 return _check_methods(C, "__iter__") 262 return NotImplemented 263 264 __class_getitem__ = classmethod(GenericAlias) 265 266 267class Iterator(Iterable): 268 269 __slots__ = () 270 271 @abstractmethod 272 def __next__(self): 273 'Return the next item from the iterator. When exhausted, raise StopIteration' 274 raise StopIteration 275 276 def __iter__(self): 277 return self 278 279 @classmethod 280 def __subclasshook__(cls, C): 281 if cls is Iterator: 282 return _check_methods(C, '__iter__', '__next__') 283 return NotImplemented 284 285 286Iterator.register(bytes_iterator) 287Iterator.register(bytearray_iterator) 288#Iterator.register(callable_iterator) 289Iterator.register(dict_keyiterator) 290Iterator.register(dict_valueiterator) 291Iterator.register(dict_itemiterator) 292Iterator.register(list_iterator) 293Iterator.register(list_reverseiterator) 294Iterator.register(range_iterator) 295Iterator.register(longrange_iterator) 296Iterator.register(set_iterator) 297Iterator.register(str_iterator) 298Iterator.register(tuple_iterator) 299Iterator.register(zip_iterator) 300 301 302class Reversible(Iterable): 303 304 __slots__ = () 305 306 @abstractmethod 307 def __reversed__(self): 308 while False: 309 yield None 310 311 @classmethod 312 def __subclasshook__(cls, C): 313 if cls is Reversible: 314 return _check_methods(C, "__reversed__", "__iter__") 315 return NotImplemented 316 317 318class Generator(Iterator): 319 320 __slots__ = () 321 322 def __next__(self): 323 """Return the next item from the generator. 324 When exhausted, raise StopIteration. 325 """ 326 return self.send(None) 327 328 @abstractmethod 329 def send(self, value): 330 """Send a value into the generator. 331 Return next yielded value or raise StopIteration. 332 """ 333 raise StopIteration 334 335 @abstractmethod 336 def throw(self, typ, val=None, tb=None): 337 """Raise an exception in the generator. 338 Return next yielded value or raise StopIteration. 339 """ 340 if val is None: 341 if tb is None: 342 raise typ 343 val = typ() 344 if tb is not None: 345 val = val.with_traceback(tb) 346 raise val 347 348 def close(self): 349 """Raise GeneratorExit inside generator. 350 """ 351 try: 352 self.throw(GeneratorExit) 353 except (GeneratorExit, StopIteration): 354 pass 355 else: 356 raise RuntimeError("generator ignored GeneratorExit") 357 358 @classmethod 359 def __subclasshook__(cls, C): 360 if cls is Generator: 361 return _check_methods(C, '__iter__', '__next__', 362 'send', 'throw', 'close') 363 return NotImplemented 364 365 366Generator.register(generator) 367 368 369class Sized(metaclass=ABCMeta): 370 371 __slots__ = () 372 373 @abstractmethod 374 def __len__(self): 375 return 0 376 377 @classmethod 378 def __subclasshook__(cls, C): 379 if cls is Sized: 380 return _check_methods(C, "__len__") 381 return NotImplemented 382 383 384class Container(metaclass=ABCMeta): 385 386 __slots__ = () 387 388 @abstractmethod 389 def __contains__(self, x): 390 return False 391 392 @classmethod 393 def __subclasshook__(cls, C): 394 if cls is Container: 395 return _check_methods(C, "__contains__") 396 return NotImplemented 397 398 __class_getitem__ = classmethod(GenericAlias) 399 400 401class Collection(Sized, Iterable, Container): 402 403 __slots__ = () 404 405 @classmethod 406 def __subclasshook__(cls, C): 407 if cls is Collection: 408 return _check_methods(C, "__len__", "__iter__", "__contains__") 409 return NotImplemented 410 411 412class Callable(metaclass=ABCMeta): 413 414 __slots__ = () 415 416 @abstractmethod 417 def __call__(self, *args, **kwds): 418 return False 419 420 @classmethod 421 def __subclasshook__(cls, C): 422 if cls is Callable: 423 return _check_methods(C, "__call__") 424 return NotImplemented 425 426 __class_getitem__ = classmethod(GenericAlias) 427 428 429### SETS ### 430 431 432class Set(Collection): 433 434 """A set is a finite, iterable container. 435 436 This class provides concrete generic implementations of all 437 methods except for __contains__, __iter__ and __len__. 438 439 To override the comparisons (presumably for speed, as the 440 semantics are fixed), redefine __le__ and __ge__, 441 then the other operations will automatically follow suit. 442 """ 443 444 __slots__ = () 445 446 def __le__(self, other): 447 if not isinstance(other, Set): 448 return NotImplemented 449 if len(self) > len(other): 450 return False 451 for elem in self: 452 if elem not in other: 453 return False 454 return True 455 456 def __lt__(self, other): 457 if not isinstance(other, Set): 458 return NotImplemented 459 return len(self) < len(other) and self.__le__(other) 460 461 def __gt__(self, other): 462 if not isinstance(other, Set): 463 return NotImplemented 464 return len(self) > len(other) and self.__ge__(other) 465 466 def __ge__(self, other): 467 if not isinstance(other, Set): 468 return NotImplemented 469 if len(self) < len(other): 470 return False 471 for elem in other: 472 if elem not in self: 473 return False 474 return True 475 476 def __eq__(self, other): 477 if not isinstance(other, Set): 478 return NotImplemented 479 return len(self) == len(other) and self.__le__(other) 480 481 @classmethod 482 def _from_iterable(cls, it): 483 '''Construct an instance of the class from any iterable input. 484 485 Must override this method if the class constructor signature 486 does not accept an iterable for an input. 487 ''' 488 return cls(it) 489 490 def __and__(self, other): 491 if not isinstance(other, Iterable): 492 return NotImplemented 493 return self._from_iterable(value for value in other if value in self) 494 495 __rand__ = __and__ 496 497 def isdisjoint(self, other): 498 'Return True if two sets have a null intersection.' 499 for value in other: 500 if value in self: 501 return False 502 return True 503 504 def __or__(self, other): 505 if not isinstance(other, Iterable): 506 return NotImplemented 507 chain = (e for s in (self, other) for e in s) 508 return self._from_iterable(chain) 509 510 __ror__ = __or__ 511 512 def __sub__(self, other): 513 if not isinstance(other, Set): 514 if not isinstance(other, Iterable): 515 return NotImplemented 516 other = self._from_iterable(other) 517 return self._from_iterable(value for value in self 518 if value not in other) 519 520 def __rsub__(self, other): 521 if not isinstance(other, Set): 522 if not isinstance(other, Iterable): 523 return NotImplemented 524 other = self._from_iterable(other) 525 return self._from_iterable(value for value in other 526 if value not in self) 527 528 def __xor__(self, other): 529 if not isinstance(other, Set): 530 if not isinstance(other, Iterable): 531 return NotImplemented 532 other = self._from_iterable(other) 533 return (self - other) | (other - self) 534 535 __rxor__ = __xor__ 536 537 def _hash(self): 538 """Compute the hash value of a set. 539 540 Note that we don't define __hash__: not all sets are hashable. 541 But if you define a hashable set type, its __hash__ should 542 call this function. 543 544 This must be compatible __eq__. 545 546 All sets ought to compare equal if they contain the same 547 elements, regardless of how they are implemented, and 548 regardless of the order of the elements; so there's not much 549 freedom for __eq__ or __hash__. We match the algorithm used 550 by the built-in frozenset type. 551 """ 552 MAX = sys.maxsize 553 MASK = 2 * MAX + 1 554 n = len(self) 555 h = 1927868237 * (n + 1) 556 h &= MASK 557 for x in self: 558 hx = hash(x) 559 h ^= (hx ^ (hx << 16) ^ 89869747) * 3644798167 560 h &= MASK 561 h = h * 69069 + 907133923 562 h &= MASK 563 if h > MAX: 564 h -= MASK + 1 565 if h == -1: 566 h = 590923713 567 return h 568 569 570Set.register(frozenset) 571 572 573class MutableSet(Set): 574 """A mutable set is a finite, iterable container. 575 576 This class provides concrete generic implementations of all 577 methods except for __contains__, __iter__, __len__, 578 add(), and discard(). 579 580 To override the comparisons (presumably for speed, as the 581 semantics are fixed), all you have to do is redefine __le__ and 582 then the other operations will automatically follow suit. 583 """ 584 585 __slots__ = () 586 587 @abstractmethod 588 def add(self, value): 589 """Add an element.""" 590 raise NotImplementedError 591 592 @abstractmethod 593 def discard(self, value): 594 """Remove an element. Do not raise an exception if absent.""" 595 raise NotImplementedError 596 597 def remove(self, value): 598 """Remove an element. If not a member, raise a KeyError.""" 599 if value not in self: 600 raise KeyError(value) 601 self.discard(value) 602 603 def pop(self): 604 """Return the popped value. Raise KeyError if empty.""" 605 it = iter(self) 606 try: 607 value = next(it) 608 except StopIteration: 609 raise KeyError from None 610 self.discard(value) 611 return value 612 613 def clear(self): 614 """This is slow (creates N new iterators!) but effective.""" 615 try: 616 while True: 617 self.pop() 618 except KeyError: 619 pass 620 621 def __ior__(self, it): 622 for value in it: 623 self.add(value) 624 return self 625 626 def __iand__(self, it): 627 for value in (self - it): 628 self.discard(value) 629 return self 630 631 def __ixor__(self, it): 632 if it is self: 633 self.clear() 634 else: 635 if not isinstance(it, Set): 636 it = self._from_iterable(it) 637 for value in it: 638 if value in self: 639 self.discard(value) 640 else: 641 self.add(value) 642 return self 643 644 def __isub__(self, it): 645 if it is self: 646 self.clear() 647 else: 648 for value in it: 649 self.discard(value) 650 return self 651 652 653MutableSet.register(set) 654 655 656### MAPPINGS ### 657 658 659class Mapping(Collection): 660 661 __slots__ = () 662 663 """A Mapping is a generic container for associating key/value 664 pairs. 665 666 This class provides concrete generic implementations of all 667 methods except for __getitem__, __iter__, and __len__. 668 669 """ 670 671 @abstractmethod 672 def __getitem__(self, key): 673 raise KeyError 674 675 def get(self, key, default=None): 676 'D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.' 677 try: 678 return self[key] 679 except KeyError: 680 return default 681 682 def __contains__(self, key): 683 try: 684 self[key] 685 except KeyError: 686 return False 687 else: 688 return True 689 690 def keys(self): 691 "D.keys() -> a set-like object providing a view on D's keys" 692 return KeysView(self) 693 694 def items(self): 695 "D.items() -> a set-like object providing a view on D's items" 696 return ItemsView(self) 697 698 def values(self): 699 "D.values() -> an object providing a view on D's values" 700 return ValuesView(self) 701 702 def __eq__(self, other): 703 if not isinstance(other, Mapping): 704 return NotImplemented 705 return dict(self.items()) == dict(other.items()) 706 707 __reversed__ = None 708 709 710Mapping.register(mappingproxy) 711 712 713class MappingView(Sized): 714 715 __slots__ = '_mapping', 716 717 def __init__(self, mapping): 718 self._mapping = mapping 719 720 def __len__(self): 721 return len(self._mapping) 722 723 def __repr__(self): 724 return '{0.__class__.__name__}({0._mapping!r})'.format(self) 725 726 __class_getitem__ = classmethod(GenericAlias) 727 728 729class KeysView(MappingView, Set): 730 731 __slots__ = () 732 733 @classmethod 734 def _from_iterable(self, it): 735 return set(it) 736 737 def __contains__(self, key): 738 return key in self._mapping 739 740 def __iter__(self): 741 yield from self._mapping 742 743 744KeysView.register(dict_keys) 745 746 747class ItemsView(MappingView, Set): 748 749 __slots__ = () 750 751 @classmethod 752 def _from_iterable(self, it): 753 return set(it) 754 755 def __contains__(self, item): 756 key, value = item 757 try: 758 v = self._mapping[key] 759 except KeyError: 760 return False 761 else: 762 return v is value or v == value 763 764 def __iter__(self): 765 for key in self._mapping: 766 yield (key, self._mapping[key]) 767 768 769ItemsView.register(dict_items) 770 771 772class ValuesView(MappingView, Collection): 773 774 __slots__ = () 775 776 def __contains__(self, value): 777 for key in self._mapping: 778 v = self._mapping[key] 779 if v is value or v == value: 780 return True 781 return False 782 783 def __iter__(self): 784 for key in self._mapping: 785 yield self._mapping[key] 786 787 788ValuesView.register(dict_values) 789 790 791class MutableMapping(Mapping): 792 793 __slots__ = () 794 795 """A MutableMapping is a generic container for associating 796 key/value pairs. 797 798 This class provides concrete generic implementations of all 799 methods except for __getitem__, __setitem__, __delitem__, 800 __iter__, and __len__. 801 802 """ 803 804 @abstractmethod 805 def __setitem__(self, key, value): 806 raise KeyError 807 808 @abstractmethod 809 def __delitem__(self, key): 810 raise KeyError 811 812 __marker = object() 813 814 def pop(self, key, default=__marker): 815 '''D.pop(k[,d]) -> v, remove specified key and return the corresponding value. 816 If key is not found, d is returned if given, otherwise KeyError is raised. 817 ''' 818 try: 819 value = self[key] 820 except KeyError: 821 if default is self.__marker: 822 raise 823 return default 824 else: 825 del self[key] 826 return value 827 828 def popitem(self): 829 '''D.popitem() -> (k, v), remove and return some (key, value) pair 830 as a 2-tuple; but raise KeyError if D is empty. 831 ''' 832 try: 833 key = next(iter(self)) 834 except StopIteration: 835 raise KeyError from None 836 value = self[key] 837 del self[key] 838 return key, value 839 840 def clear(self): 841 'D.clear() -> None. Remove all items from D.' 842 try: 843 while True: 844 self.popitem() 845 except KeyError: 846 pass 847 848 def update(self, other=(), /, **kwds): 849 ''' D.update([E, ]**F) -> None. Update D from mapping/iterable E and F. 850 If E present and has a .keys() method, does: for k in E: D[k] = E[k] 851 If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v 852 In either case, this is followed by: for k, v in F.items(): D[k] = v 853 ''' 854 if isinstance(other, Mapping): 855 for key in other: 856 self[key] = other[key] 857 elif hasattr(other, "keys"): 858 for key in other.keys(): 859 self[key] = other[key] 860 else: 861 for key, value in other: 862 self[key] = value 863 for key, value in kwds.items(): 864 self[key] = value 865 866 def setdefault(self, key, default=None): 867 'D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D' 868 try: 869 return self[key] 870 except KeyError: 871 self[key] = default 872 return default 873 874 875MutableMapping.register(dict) 876 877 878### SEQUENCES ### 879 880 881class Sequence(Reversible, Collection): 882 883 """All the operations on a read-only sequence. 884 885 Concrete subclasses must override __new__ or __init__, 886 __getitem__, and __len__. 887 """ 888 889 __slots__ = () 890 891 @abstractmethod 892 def __getitem__(self, index): 893 raise IndexError 894 895 def __iter__(self): 896 i = 0 897 try: 898 while True: 899 v = self[i] 900 yield v 901 i += 1 902 except IndexError: 903 return 904 905 def __contains__(self, value): 906 for v in self: 907 if v is value or v == value: 908 return True 909 return False 910 911 def __reversed__(self): 912 for i in reversed(range(len(self))): 913 yield self[i] 914 915 def index(self, value, start=0, stop=None): 916 '''S.index(value, [start, [stop]]) -> integer -- return first index of value. 917 Raises ValueError if the value is not present. 918 919 Supporting start and stop arguments is optional, but 920 recommended. 921 ''' 922 if start is not None and start < 0: 923 start = max(len(self) + start, 0) 924 if stop is not None and stop < 0: 925 stop += len(self) 926 927 i = start 928 while stop is None or i < stop: 929 try: 930 v = self[i] 931 if v is value or v == value: 932 return i 933 except IndexError: 934 break 935 i += 1 936 raise ValueError 937 938 def count(self, value): 939 'S.count(value) -> integer -- return number of occurrences of value' 940 return sum(1 for v in self if v is value or v == value) 941 942 943Sequence.register(tuple) 944Sequence.register(str) 945Sequence.register(range) 946Sequence.register(memoryview) 947 948 949class ByteString(Sequence): 950 951 """This unifies bytes and bytearray. 952 953 XXX Should add all their methods. 954 """ 955 956 __slots__ = () 957 958ByteString.register(bytes) 959ByteString.register(bytearray) 960 961 962class MutableSequence(Sequence): 963 964 __slots__ = () 965 966 """All the operations on a read-write sequence. 967 968 Concrete subclasses must provide __new__ or __init__, 969 __getitem__, __setitem__, __delitem__, __len__, and insert(). 970 971 """ 972 973 @abstractmethod 974 def __setitem__(self, index, value): 975 raise IndexError 976 977 @abstractmethod 978 def __delitem__(self, index): 979 raise IndexError 980 981 @abstractmethod 982 def insert(self, index, value): 983 'S.insert(index, value) -- insert value before index' 984 raise IndexError 985 986 def append(self, value): 987 'S.append(value) -- append value to the end of the sequence' 988 self.insert(len(self), value) 989 990 def clear(self): 991 'S.clear() -> None -- remove all items from S' 992 try: 993 while True: 994 self.pop() 995 except IndexError: 996 pass 997 998 def reverse(self): 999 'S.reverse() -- reverse *IN PLACE*' 1000 n = len(self) 1001 for i in range(n//2): 1002 self[i], self[n-i-1] = self[n-i-1], self[i] 1003 1004 def extend(self, values): 1005 'S.extend(iterable) -- extend sequence by appending elements from the iterable' 1006 if values is self: 1007 values = list(values) 1008 for v in values: 1009 self.append(v) 1010 1011 def pop(self, index=-1): 1012 '''S.pop([index]) -> item -- remove and return item at index (default last). 1013 Raise IndexError if list is empty or index is out of range. 1014 ''' 1015 v = self[index] 1016 del self[index] 1017 return v 1018 1019 def remove(self, value): 1020 '''S.remove(value) -- remove first occurrence of value. 1021 Raise ValueError if the value is not present. 1022 ''' 1023 del self[self.index(value)] 1024 1025 def __iadd__(self, values): 1026 self.extend(values) 1027 return self 1028 1029 1030MutableSequence.register(list) 1031MutableSequence.register(bytearray) # Multiply inheriting, see ByteString 1032