# Python : Core : Types
- [reference/datamodel](https://docs.python.org/3/reference/datamodel.html)
- [library/stdtypes](https://docs.python.org/3/library/stdtypes.html)
- [library/collections](https://docs.python.org/3/library/collections.html)
- [library/collections.abc](https://docs.python.org/3/library/collections.abc.html)
- [library/decimal](https://docs.python.org/3/library/decimal.html)
- [library/enum](https://docs.python.org/3/library/enum.html)
- [library/numbers](https://docs.python.org/3/library/numbers.html)
- [library/uuid](https://docs.python.org/3/library/uuid.html)
## Basics
The principal built-in types are *numerics*, *sequences*, *mappings*, *classes*, *instances* and *exceptions*. (Strings are sequences.)
Everything is an object with a type (returned by `type()`), a value, and a constant identity (returned by `id()` and compared with `is`).
Some objects are "containers", which contain references to other objects.
#### Constructors
```python
# Built-in
bool(), bytearrays(), bytes(), complex(), dict(), float(), frozenset(),
int(), list(), range(), set(), slice(), str(), tuple()
# Standard Library
datetime : date(), datetime(), time()
decimal : Decimal()
enum : Enum()
uuid : UUID()
```
#### Special Values
- `None` is both a type and a value.
- `NotImplemented` is both a type and a value. *(Numeric methods and rich comparison methods should return this value if they do not implement the operation for the operands provided.)*
- `...` is the literal for the `Ellipsis` value, which is the only instance of `types.EllipsisType`
#### Numbers
###### Booleans
A subclass of `int` with instances `True` and `False`, which evaluate to `1` and `0` in numeric contexts.
###### Truthiness
By default, an object is considered true unless its class defines either:
- a `__bool__()` method that returns `False`
- a `__len__()` method that returns `0`
> [!info] Falsy Values
> ```python
> False, None, 0, 0.0, "", [], (), {}, set(), range(0)
> ```
###### Ints & Floats
```python
# turn floats into ints
math.trunc( x )
math.floor( x )
math.ceil( x )
int.bit_length() # min necessary to represent value
int.bit_count() # count of 1s
int.to_bytes( ... ) # https://docs.python.org/3/library/stdtypes.html#int.to_bytes
int.from_bytes( ... ) # https://docs.python.org/3/library/stdtypes.html#int.from_bytes
int.is_integer()
float.is_integer()
```
###### Decimals
```python
Decimal( 0.1 ) -> Decimal( "0.1000000000000000055511151231257827021181583404541015625" )
Decimal( "0.1" ) -> Decimal( "0.1" )
Decimal( "0.10" ) -> Decimal( "0.10" )
Decimal( "7.325" ).quantize( Decimal( ".01" ), rounding = ROUND_DOWN ) -> Decimal( "7.32" )
Decimal( "7.325" ).quantize( Decimal( "1." ), rounding = ROUND_UP ) -> Decimal( "8" )
# Decimal objects cannot generally be combined with floats in arithmetic operations
Decimal( 5 ) + 5.0 -> TypeError
```
###### Abstract Base Classes
Supports `isinstance` and `issubclass` functions.
- `int` is considered a subclass of `Integral`
- `float` is considered a subclass of `Real`
- `decimal.Decimal` is considered a subclass of `Number`
```python
numbers import Complex, Integral, Number, Rational, Real
Number > Complex > Real > Rational > Integral
```
## Collections
```
Sequence -> ordered collection with indexing and slicing
Immutable -> bytes, range, str, tuple
Mutable -> bytearray, list
Set -> unordered collection of distinct, hashable objects; no indexing or slicing
Immutable -> frozenset
Mutable -> set
Mapping -> ordered collection of value objects indexed by arbitrary hashable key objects
Mutable -> dict (preserves order)
Callable -> functions, methods, classes, instances that define __call__
```
#### Slicing
```python
a[ i:j ] # returns list of elements starting at i and stopping before j
a[ i:j:s ] # s = "step"; aka "extended slice"
a[ i:j ] = iterable # replace slice with contents of iterable
a[ i:i ] = iterable # insert contents of iterable before position i
del a[ i:j ] # element deletion
```
#### ABC
Abstract base classes for testing whether a class provides a particular interface.
Some simple interfaces are recognizable by the presence of required methods:
```python
class E:
def __iter__( self ): ...
def __next__( next ): ...
issubclass( E, Iterable ) -> True
isinstance( E(), Iterable ) -> True
```
Complex interfaces do not support this technique because an interface is more than a set of methods — they specify semantics and relationships between methods that cannot be inferred from method presence.
For example, knowing that a class supplies `__getitem__`, `__len__`, and `__iter__` is insufficient for distinguishing a `Sequence` from a `Mapping`.
```python
class C( Sequence ):
def __getitem__( self, key ): ...
def __len__( self ): ...
def __iter__( self ): ...
```
| Class | Required Methods | Inherited Methods |
| ------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| Container | `__contains__` | |
| Hashable | `__hash__` | |
| Iterable | `__iter__` | |
| Iterator < Iterable | `__next__` | `__iter__` |
| Reversible < Iterable | `__reversed__` | |
| Generator < Iterator | `send`, `throw` | `close`, `__iter__`, `__next__` |
| Sized | `__len__` | |
| Callable | `__call__` | |
| Collection < Sized Iterable Container | `__contains__`, `__iter__`, `__len__` | |
| Sequence < Reversible Collection | `__getitem__`, `__len__` | `__contains__`, `__iter__`, `__reversed__`, `index`, `count` |
| MutableSequence < Sequence | `__getitem__`, `__setitem__`, `__delitem__`, `__len__`, `insert` | Sequence methods + `append`, `reverse`, `extend`, `pop`, `remove`, `__iadd__` |
| ByteString < Sequence | `__getitem__`, `__len__` | Sequence methods |
| Set < Collection | `__contains__`, `__iter__`, `__len__` | `__le__`, `__lt__`, `__eq__`, `__ne__`, `__gt__`, `__ge__`, `__and__`, `__or__`, `__sub__`, `__xor__`, `isdisjoint` |
| MutableSet < Set | `__contains__`, `__iter__`, `__len__`, `add`, `discard` | Set methods + `clear`, `pop`, `remove`, `__ior__`, `__iand__`, `__ixor__`, `__isub__` |
| Mapping < Collection | `__getitem__`, `__iter__`, `__len__` | `__contains__`, `keys`, `items`, `values`, `get`, `__eq__`, `__ne__` |
| MutableMapping < Mapping | `__getitem__`, `__setitem__`, `__delitem__`, `__iter__`, `__len__` | Mapping methods + `pop`, `popitem`, `clear`, `update`, `setdefault` |
| MappingView < Sized | | `__len__` |
| ItemsView < MappingView, Set | | `__contains__`, `__iter__` |
| KeysView < MappingView, Set | | `__contains__`, `__iter__` |
| ValuesView < MappingView, Collection | | `__contains__`, `__iter__` |
| Awaitable | `__await__` | |
| Coroutine < Awaitable | `send`, `throw` | `close` |
| AsyncIterable | `__aiter__` | |
| AsyncIterator < AsyncIterable | `__anext__` | `__aiter__` |
| AsyncGenerator < AsyncIterator | `asend`, `athrow` | `aclose`, `__aiter__`, `__anext__` |
| Buffer | `__buffer__` | |
#### APIs
###### Sequences
```python
x in s, x not in s
s + t, s * n, n * s
s[ i ], s[ i:j ], s[ i:j:k ]
len( s ), min( s ), max( s )
s.index( x[, i[, j ] ] ) # first occurrence of x in s (or in the slice i:j)
# raises ValueError if not found
s.count( x )
```
> [!NOTE] range()
> ```
> immutable sequence type
> range( stop )
> range( start, stop[, step] )
> r = range( 1, 5 )
> list( r ) -> [ 1, 2, 3, 4]
> len( r ) -> 4
> 4 in r -> True
> 5 in r -> False
> ```
###### Mutable Sequences
```python
s[ i ] = x
s[ i:j ] = t
s[ i:j:k ] = t
del s[ ... ]
s.append( x )
s.clear()
s.copy() # returns shallow copy; same as s[:]
s.extend( t ) # same as: s += t
s *= n
s.insert( i, x ) # same as: s[ i:i ] = x
s.pop( i=-1 ) # remove and return element at i
s.remove( x ) # remove first occurence
s.reverse() # in-place
list.sort( *, key=None, reverse=False ) # in-place
```
###### Sets
```python
e in s
len( s )
for e in s:
s.add( elem )
s.update( *iter ) # add elements from zero or more iterables
s.remove( elem )
s.isdisjoint( other ) # True if intersection of sets is empty
s <= other s.issubset( other ) # True if subset or equal
s < other # True if subset and not equal
s >= other s.issuperset( other )
s > other
s | other | ... s.union( *others )
s & other & ... s.intersection( *others )
s - other - ... s.difference( *others )
s ^ other s.symmetric_difference( other )
s.copy()
```
###### Mappings (Dicts)
```python
dict.fromkeys( iterable[, value] ) # iterable of keys plus optional value
list( d ) # -> list of keys
tuple( d ) # -> tuple of keys
len( d ) # -> int of item count
d[ key ] # -> returns value or calls __missing__() or raises KeyError
d[ key ] = value
del d[ key ] # -> raises KeyError
key in d, key not in d
iter( d ) # -> iter for keys; shortcut for iter( d.keys() )
d.clear()
d.copy() # -> shallow copy
d.get( key[, default] )
d.items() # -> dict_items| ( k1, v1 ), ... |
d.keys() # -> dict_keys| k1, ... |
d.pop( key[, default] ) # remove and return value or return default or raise KeyError
d.popitem() # LIFO order; -> ( k, v )
reversed( d ) # -> iter for keys in reverse; shortcut for reversed( d.keys() )
d.setdefault( key, default=None )
d.update( other )
d.values() # -> dict_values| v1, ... |
d | other # returns new merged dict; other has priority
d |= other # equiv to d.update( other )
# dict_items, dict_keys, and dict_values are "Dictionary View" classes.
```
###### Dictionary View Objects
```python
len( dv )
iter( dv )
x in dv
reversed( dv )
dv.mapping # -> original dict
# `dict_keys` also supports set operations
```
## Collections Module
```python3
ChainMap < MutableMapping # virtual view of multiple mappings
Counter < dict # for counting hashable objects
defaultdict < dict # calls factory function to supply missing values
deque < object # list-like, with fast mutations on either end
namedtuple() # factory function for creating tuple subclasses
# with named fields accessible as attributes
OrderedDict < dict # OBSOLETE (only trivial differences from normal dicts)
UserDict < MutableMapping # wrapper around dict objects for easier subclassing
UserList < MutableMapping # wrapper around list objects for easier subclassing
UserString < Sequence # wrapper around str objects for easier subclassing
```
###### ChainMap
```python
cm = ChainMap( *maps )
cm.maps
```
- like `dict` but with `.maps` attribute
- lookups search the maps in order
- mutations only touch the first mapping
###### Counter
- For new keys, inits `0` instead of `None`.
- For missing keys, returns `0` instead of raising `KeyError`.
- Objects be compared for equality and superset/subset relationships.
- Objects be added and subtracted.
```python
cnt = Counter( [iter-or-map] )
# For new keys, inits 0 instead of None.
# For missing keys, returns 0 instead of raising KeyError.
cnt = Counter( words )
-or-
cnt = Counter()
for word in words
cnt[ word ] += 1
cnt[ word ] # returns 0+
cnt.elements() # returns iterator:
# each key K, in occurrence order, repeated cnt[ k ] times
cnt.most_common( [n] ) # if None, returns all, ordered most to least
# if n, returns top n
# n=3 -> [ ( 'foo', 13 ), ( 'bar', 8 ), ( 'baz', 7 ) ]
cnt.subtract( [iter-or-map] ) # decrement counter for each occurence
cnt.total() # sum of counts
cnt.update( [iter-or-map] ) # increments counts instead of replacing values
```
###### defaultdict
```python
defaultdict( default_factory=None, **kwargs )
```
`default_factory` should be a callable that takes no arguments. It will be called to initialize the value of missing keys.
###### namedtuple()
Returns custom subclass of `tuple` named `typename` with named fields accessible as attributes and helpful docstring and `__repr__()` implementation. The subclass constructor will accept both positional and keyword arguments for those fields. Instances can be used anywhere a regular tuple can be.
```python
namedtuple( typename, field_names, *, rename=False, defaults=None, module=None )
# field_names -> either a list of strings, or a string of field names
# separated by whitespace and/or commas
# defaults -> an optional list of default values (applied from the right side)
# module -> set __module__ attribute (defaults to current module)
Point = namedtuple( "Point", [ "latitude", "longitude" ] )
Point = namedtuple( "Point", "latitude longitude" )
p = Point( 1.2, 3.4 )
p = Point( longitude=3.4, latitude=1.2 )
p.latitude # -> 1.2
p[ 0 ] # -> 1.2
# extra attributes (beyond standard tuple API)
p._asdict() # -> { ... }
p._replace( **kwargs ) # -> new Point with replaced values
p._fields # -> ( 'latitude', 'longitude' )
p._field_defaults # -> { field: default }
```
###### User* classes
The `User`* classes simulate their respective built-in types, and were created to facilitate subclassing. Now you can subclass directly from `dict`, `list`, and `str`. However, these classes can be easier to work with because the underlying contents are stored in a `data` attribute.
```python
UserDict( [initialdata] )
.data -> actual dict (stores contents)
UserList( [list] )
.data -> actual list (stores contents)
UserString( seq )
.data -> actual str (stores contents)
```
## Iterators and Generators
```python
iterator = container.__iter__()
iterator.__iter__() # return self
iterator.__next__() # return next item or raise StopIteration
```