<jupyter_start><jupyter_text>Think like a Pythonista <NAME>, principal consultant @ThoughtWorks [@standupdev](https://twitter.com/standupdev) and [@ramalhoorg](https://twitter.com/ramalhoorg) on Twitter This is a Jupyter Notebook. It's made of *cells* with code that can be edited and executed interactively.<jupyter_code>2**200<jupyter_output><empty_output><jupyter_text>Now, for the main event...  A class to represent a playing card<jupyter_code>from collections import namedtuple

Card = namedtuple('Card', 'rank suit')
beer_card = Card('7', 'diamonds')
beer_card
rank, suit = beer_card
rank, suit
beer_card.suit
beer_card.rank<jupyter_output><empty_output><jupyter_text>Suits and ranks<jupyter_code>SUITS = 'clubs diamonds spades hearts'.split()
SUITS
RANKS = [str(n) for n in range(2, 11)] + list('JQKA')
RANKS
CARDS = [Card(r, s) for s in SUITS for r in RANKS]
len(CARDS)
CARDS<jupyter_output><empty_output><jupyter_text>The Deck class<jupyter_code>class Deck:
    def __init__(self):
        self._cards = list(CARDS)
        
    def __len__(self):
        return len(self._cards)
    
    def __getitem__(self, i):
        return self._cards[i]
deck = Deck()
len(deck)
deck[0]
deck[-1]
deck[:5]<jupyter_output><empty_output><jupyter_text>Iteration<jupyter_code>for card in deck:
    print(card)
it = iter(deck)
it
next(it)<jupyter_output><empty_output><jupyter_text>Sorting<jupyter_code>SPADES_HIGH = sorted(SUITS)

def index(card):
    """Card position in spades high ordering"""
    rank_value = RANKS.index(card.rank)
    return rank_value * len(SPADES_HIGH) + SPADES_HIGH.index(card.suit)
index(Card('2', 'clubs'))
index(Card('A', 'spades'))
sorted(deck, key=index)<jupyter_output><empty_output><jupyter_text>Randomizing<jupyter_code>import random
random.choice('ABCDE')
random.choice(deck)
l = list(range(20))
random.shuffle(l)
l
try:
    random.shuffle(deck)
except TypeError as e:
    print(repr(e))<jupyter_output>TypeError("'Deck' object does not support item assignment",)<jupyter_text>Monkey-patching Deck to support item assignment<jupyter_code>def put(deck, position, card):
    deck._cards[position] = card
        
Deck.__setitem__ = put
random.shuffle(deck)
deck[:5]<jupyter_output><empty_output><jupyter_text>Bonus: operator overloading<jupyter_code>from itertools import chain

class Deck:
    def __init__(self, cards=CARDS):
        self._cards = list(cards)
        
    def __len__(self):
        return len(self._cards)
    
    def __getitem__(self, i):
        if isinstance(i, slice):
            return Deck(self._cards[i])
        return self._cards[i]
    
    def __setitem__(self, i, card):
        self._cards[i] = card
        
    def __add__(self, other):
        return Deck(chain(self._cards, other))
    
    def deal(self, num_players):
        return [self[i::num_players] for i in range(num_players)]
                
#chain?
deck = Deck()
top5 = deck[:5]
top5
for card in top5:
    print(card)
bottom5 = deck[-5:]
for card in bottom5:
    print(card)
top5 + bottom5
for card in top5 + bottom5:
    print(card)
random.shuffle(deck)
a, b, c, d = deck.deal(4)
len(a), len(b)
for card in c:
    print(card)<jupyter_output>Card(rank='7', suit='hearts')
Card(rank='A', suit='diamonds')
Card(rank='3', suit='spades')
Card(rank='J', suit='spades')
Card(rank='4', suit='hearts')
Card(rank='Q', suit='diamonds')
Card(rank='8', suit='clubs')
Card(rank='2', suit='hearts')
Card(rank='3', suit='hearts')
Card(rank='9', suit='diamonds')
Card(rank='5', suit='spades')
Card(rank='K', suit='clubs')
Card(rank='2', suit='diamonds')<jupyter_text>And now, for something completely different... The beauty of operator overloading for analytics.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt

v0 = 5
g = 9.81
t = np.linspace(0, 1, 1001)

y = v0 * t - g * t**2 / 2

plt.plot(t, y)
plt.xlabel('t (s)')
plt.ylabel('y (m)')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14508700102354144, 'fraction_numerical': 0.0127942681678608, 'mean_word_length': 4.8870481927710845, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 40, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '474804', 'license': 'MIT', 'n_tokens_mistral': 1490, 'n_tokens_neox': 1452, 'n_words': 325, 'path': 'think-like-a-pythonista.ipynb', 'repo_name': 'ramalho/pense-como-pythonista', 'size': '3917'}