<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def deal(self, num=1, rebuild=False, shuffle=False, end=TOP):
 """ Returns a list of cards, which are removed from the deck. :arg int num: The number of cards to deal. :arg bool rebuild: Whether or not to rebuild the deck when cards run out. :arg bool shuffle: Whether or not to shuffle on rebuild. :arg str end: The end of the ``Stack`` to add the cards to. Can be ``TOP`` ("top") or ``BOTTOM`` ("bottom"). :returns: A given number of cards from the deck. """

        _num = num

        rebuild = rebuild or self.rebuild
        re_shuffle = shuffle or self.re_shuffle

        self_size = self.size

        if rebuild or num <= self_size:
            dealt_cards = [None] * num
        elif num > self_size:
            dealt_cards = [None] * self_size

        while num > 0:
            ends = {TOP: self.cards.pop, BOTTOM: self.cards.popleft}
            n = _num - num
            try:
                card = ends[end]()
                dealt_cards[n] = card
                num -= 1
            except:
                if self.size == 0:
                    if rebuild:
                        self.build()
                        if re_shuffle:
                            self.shuffle()
                    else:
                        break

        return Stack(cards=dealt_cards)