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
genexp
to 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 fixed
and 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
None
to make it clear to the caller that the object itself was changed, and no new object was created
- No need to implement
random card
method, asrandom
function 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%r
to 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
concatenation
ofimmutable
sequences isinefficient
, because instead of just appending new items, the interpreter has tocopy the whole target sequence
tocreate a new one
with 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.UserDict
and 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