| representation | methods |
|---|---|
| string/bytes representation | __repr__, __str__, __format__, __bytes__ |
| conversion to number | __abs__, __bool__, __complex__, __int__, __float__, __hash__, __index__ |
| emulating collections | __len__, __getitem__, __setitem__, __delitem__, __contains__ |
| iteration | __iter__, __reversed__, __next__ |
| emulating callables | __call__ |
| context management | __enter__, __exit__ |
| instance creation and destruction | __new__, __init__, __del__ |
| attribute management | __getattr__, __getattribute__, __setattr__, __delattr__, __dir__ |
| attribute descriptors | __get__, __set__, __delete__ |
| class services | __prepare__, __instancecheck__, __subclasscheck__ |
| unary numeric operators | __neg__, -, __pos__, +, __abs__ |
| rich compartison operators | __lt__, >, __le__, <=, __eq__, ==, __ne__, !=, __gt__, >, __ge__, >= |
| arithmetic operators | __add__, +, __sub__, -, __mul__, *,__truediv__, /,__floordiv__,//,__mod__, %, __divmod__, __pow__ **, __round__ |
| reversed arithmetic operators | __radd__, __rsub__, __rmul__, __rtruediv__, __rfloordiv__, __rmod__, __rdivmod__, __rpow__ |
| arithmetic operators | __iadd__, __isub__, __imul__, __itruediv__, __ifloordiv__, __imod__, __ipow__ |
| bitwise operators | __invert__, ~, __lshift__, <<, __rshift__, >>, __and__, &, __or__, ` |
| reversed bitwise operators | __rlshift__, __rrshift__, __rand__, __rxor__, __ror__ |
Python Data Model- describes python as a framework
- enables custom objects to interact with basic language constructs
Dunder methods-__getitem__
__repr__ |
__str__ |
|---|---|
unambigous as it gets the standard representation of the object |
ambiguous as gets the string representation (lose info) |
%r |
%s |
called if __str__ is not implemented by the class |
Container sequences |
Flat sequences |
|---|---|
| list, tuple and collections.deque | str, bytes, bytearray, memoryview, array.array |
can hold items of many different types |
hold items of one type |
hold references to objects they contain |
physically store the value of the items within its memory space |
mutable |
immutable |
- Implement
__repr__for any class you implement. This should be second nature. Implement__str__if you think it would be useful to have a string version which errs on the side of more readability in favor of more ambiguity - Can use
genexpto save memory because it yields items one by one using the iterator protocol instead of building a whole list - using a tuple as a collection of fields -> the
number of items is often fixedand theirorder is always vital - Putting mutable items in tuples is not a good idea
- functions or methods that change an object in-place should return
Noneto make it clear to the caller that the object itself was changed, and no new object was created
- No need to implement
random cardmethod, asrandomfunction already exists (from random import choice) - implement
__setitem__to change immutable objects
import collections
Shirt = collections.namedtuple('Shirt', ['size', 'color'])
class ShirtCollection:
sizes = list('SML')
colors = 'red blue green'.split()
def __init__(self):
self._shirts = [ Shirt(size, color) for size in self.sizes
for color in self.colors]
def __len__(self):
return len(self._shirts)
def __getitem__(self, position):
return self._shirts[position]
def __setitem__(self, position, item):
self._shirts[position] = item
__repr__implementation used%rto obtain the standard representation of the attributes to be printed
colors = ['black', 'white']
sizes = ['S', 'M', 'L']
tshirts = [(color, size) for color in colors for size in sizes]
[('black', 'S'), ('black', 'M'), ('black', 'L'), ('white', 'S'),
('white', 'M'), ('white', 'L')]
for tshirt in ('%s %s' % (c, s) for c in colors for s in sizes):
... print(tshirt)
lax_coordinates = (33.9425, -118.408056)
swapping the values of variables without using a temporary variable:
b, a = a, b
prefixing an argument with a star when calling a function:
>>> t = (20, 8)
>>> divmod(*t)
(2, 4)
os.path.split() function builds a tuple (path, last_part) from a filesystem path:
>>> import os
>>> _, filename = os.path.split('/home/luciano/.ssh/idrsa.pub')
>>> filename
'idrsa.pub'
grab excess arguments with *:
>>> a, b, *rest = range(5)
>>> a, b, rest
(0, 1, [2, 3, 4])
collections.namedtuple take exactly the same amount of memory as tuples because the field names are stored in the class
- s[
start:stop:stride] - can name slices for readability
>>> l = list(range(10))
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> l[2:5] = [20, 30]
>>> l
[0, 1, 20, 30, 5, 6, 7, 8, 9]
>>> l = [1, 2, 3]
>>> l * 5
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
- Be careful with using
*to create a list of mutable items, as it will result in multiple references to the same mutable item - Repeated
concatenationofimmutablesequences isinefficient, because instead of just appending new items, the interpreter has tocopy the whole target sequencetocreate a new onewith the new items concatenated
country_code = {country: code for code, country in DIAL_CODES}
>>> country_code
{'China': 86, 'India': 91, 'Bangladesh': 880, 'United States': 1,
'Pakistan': 92, 'Japan': 81, 'Russia': 7, 'Brazil': 55, 'Nigeria':
234, 'Indonesia': 62}
if key not in my_dict: # 3 lines, 2 index lookups (3 if not found)
my_dict[key] = []
my_dict[key].append(new_value)
my_dict.setdefault(key, []).append(new_value) # one line, single index lookup
instantiate a defaultdict with a callable which used to produce a default value whenever __getitem__ is passed a non-existent key
index = collections.defaultdict(list)
- subclass
collections.UserDictand provide a__missing__method, the standarddict.__getitem__will call it whenever a key is not found, instead of raisingKeyError - UserDict does not inherit from dict, but has an internal dict instance, called
data, which holds the actual items. This avoids undesired recursion when coding special methods like__setitem__, and simplifies the coding of__contains__
StrKeyDict always converts non-string keys to str — on insertion, update and lookup
import collections
class StrKeyDict(collections.UserDict):
def __missing__(self, key):
if isinstance(key, str):
raise KeyError(key)
return self[str(key)]
def __contains__(self, key):
return str(key) in self.data
def __setitem__(self, key, item):
self.data[str(key)] = item