Sei sulla pagina 1di 3

The Python Data Model

import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2, 11) + list('JQKA')]
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Card(rank, suit) for suit in self.suits
for rank in self.ranks] # note for suit in self.suit is parent
loop
def __len__(self):
return len(self._cards)
def __getitem__(self, position):
return self._cards[position]

Obj[key] is supported by the __getitem__ special method. In order to evaluate s[key], the interpreter
calls s.__getitem__(key).

Because our __getitem__ delegates to the [] operator of self._cards, our deck automatically supports
slicing.

Just by implementing the __getitem__ special method, our deck i also iterable.

The deck can also be iterated in reverse.

If a collection has no __contains__ method, the in operator will still work because our FrenchDeck
class is iterable.

Sorting is of course also supported because its a list.

Because we did not implement __repr__ method, FrenchDeck instances will be shown in the console
like <FrenchDeck object at 0x.>. Get to know the !r field in string format, which does eg Vector(1, 2)
instead of Vector(1, 2).

__str__ which is called by str() and used by print function. If you only implement one of these special
methods, choose __repr__ because when no custor __str__ is available, python will call __repr__ as
fallback.

To implement + and * use __add__ and __mul__. Note that in both cases new object will be created.

By default instances of user-defined classes are considered truthy, unless either __bool__ or __len__
is implemented. bool(x) calls x.__bool__(). If __bool__ is not implemented, python tries to invoke
x.__len__().
An Array of Sequences
Generator Expressions (genexps) saves memory (as opposed to listcomps) because it yields items one
by one using the iterator protocol instead of building a whole list.

Neat trick:
users = [('Bartek', 1), ('Jared', 2)]
for user in users:
print('%s/%d' % user)

collections.namedtuple: takes exactly the same amount of memory as tuples because the field
names are stored in the class (not a per instance). Useful _fields, _make(iterable) and _asdict()

Naming a slice
string = 'Bartek is my name.'
name = slice(0, 6)
print string[name]

The special method that makes += work is __iadd__() for in-place addition. If __iadd__ is not
implemented python falls back to __add__.

*= is implemented via __imul__.

Putting mutable items (lists etc) in tuples in not a good idea. p45 to read on as to why.

Sorting

The list.sort methods sorts list in place. Functions or methods that change an object in place should
return None (is by default) to make it clear to the caller that the object itself was changed, and no
new object was created.

The builtin function sorter creates a new list. It accepts key argument. Key can be key=str.lower,
key=len etc.

Once your sequences are sorter, theycan be very efficiently searched. Functions of the bisect
module: bisect and insort that use the binary search algorithm finds and inserts items in any sorter
sequence.

Sorting is expensive so once you have a sorter seq its good to keep it that way. Thats why
bisect.insort was created.

If you are handling lists of numbers, arrays are the way to go. For example, is you need to store 10M
floating-point numbers, an array is much more efficient, on the other hand if you are constantly
adding and removing items from the ends of a list a deque works faster.

If your code does a lot of check with the in operator, consider using a set.
Arrays have methods tofile() fromfile() frombytes() for very fast loading and saving.

Another fast and more flexible way of saving numeric data is the pickle module/ pickls.dumps() is
almost as fast as array.tofile

As of python 3.4 array type does not have an inplace sort method. Use the sorter method to rebuild
it sorter:

a = array.array(a.typecode, strted(a))

If you are doing advances numeric processing in arrays, you should be using the NumPy and SciPy
librbries.

To change shape of an array:

a.shape = 3, 4

High-resolution performance timer.

From time import perf_counter as pc

t0 = pc()

# do something

Print pc() t0

Inserting and removing from the left of a list (the 0 index) is costly because the entire list must be
shifted, for this task use collections.deque (thread-safe). But there is a hidden cost: removing items
from the middle of a deque is not as fast. The append and popleft operatioins are atomic so deque is
safe to use as a FIFO queue in multithreaded applications without the need for using locks.

Potrebbero piacerti anche