I redid a Python Reversi move preview routine that is online. I could use comments about using Python better and/or better OOP design since the original did not use classes. There are three main classes:
Board for the Reversi board, Location to hold an x,y coordinate (0-7,0-7), and Move to store a location to put a disc on a board and how many discs would be affected by that move. I separated out Move because I would like to keep a sequence of Moves in memory to play forward or reverse. Board knows about where the discs are in two bitfields, one for each player, and knows how to turn over discs and return if a disc is at a location.


    import unittest
    import copy
    from bitarray import bitarray
    
    INITIAL_BOARD = """
    |_|_|_|_|_|_|_|_|
    |_|_|_|_|_|_|_|_|
    |_|_|_|_|_|_|_|_|
    |_|_|_|B|W|_|_|_|
    |_|_|_|W|B|_|_|_|
    |_|_|_|_|_|_|_|_|
    |_|_|_|_|_|_|_|_|
    |_|_|_|_|_|_|_|_|
    """
    
    def other_player(playerId):
        return 'B' if playerId == 'W' else 'W'
    
    class Location:
        def __init__(self,x=0,y=0):
            self.valid = True
            self.offset = self.convertToOffset(x,y)
            
        def convertToOffset(self,x,y):
            if self.valid:
                self.valid = (x >= 0 and x <= 7 and y >= 0 and y <= 7)
            return x + y * 8
    
        def translate(self,dx,dy):
            if self.valid:
                self.valid = ((self.offset >= 8 and dy == -1) or 
                    (self.offset <= 56 and dy == 1) or
                    (self.offset % 8 > 0 and dx == -1) or
                    (self.offset % 8 < 7 and dx == 1))
            self.offset = self.offset + dx + dy * 8
    
        def __eq__(self, other):
            if isinstance(other, self.__class__):
                return self.__dict__ == other.__dict__
            else:
                return False
    
        def __ne__(self, other):
            return not self.__eq__(other)
     
        
    class Board:
        def __init__(self, board=INITIAL_BOARD):
            self.discs = self.parse_board(board)
            
        def make_bitstring(self,board,color_current):
            other_color = other_player(color_current)
            def parse_to_bit(square):
                if square == color_current:
                    return '1'
                elif square == '_' or square == other_color:
                    return '0'
                return ''
            return bitarray(''.join(map(parse_to_bit,board)))
    
        def parse_board(self,board):
            return (self.make_bitstring(board,'B'),
                self.make_bitstring(board,'W'))
        
        def show(self):
            print self.discs    
            
        def at(self, location, player):
            return location.valid and self.discs[int(player=='W')][location.offset]
    
        def empty(self, location):
            return not location.valid or (not self.at (location,'B') and not self.at (location,'W'))
    
        def turnoverDisc(self, location):
            offset = location.offset
            self.discs[0][offset], self.discs[1][offset] = self.discs[1][offset], self.discs[0][offset]
    
        def placeDisc(self, location, player):
            self.discs[int(player=='W')][location.offset] = 1
    
        def __eq__(self, other):
            if isinstance(other, self.__class__):
                return self.__dict__ == other.__dict__
            else:
                return False
    
        def __ne__(self, other):
            return not self.__eq__(other)

    
    class Move:
        def __init__(self, board, location, color_player):    
            self.location = location
            self.player = color_player
            self.board = board
            self.discDelta = self.makeDiscDelta()
            
        def makeDiscDelta(self):
            result = []
            other = other_player(self.player)
            if not self.board.empty(self.location):
                return result
            next_location = Location()
            for dir in [(1,0),(1,-1),(0,-1),(-1,-1),(-1,0),(-1,1),(0,1),(1,1)]:
                next_location.offset = self.location.offset
                next_location.translate(dir[0],dir[1])
                dirDelta = []
                while self.board.at(next_location,other):
                    dirDelta.append(copy.copy(next_location))
                    next_location.translate(dir[0],dir[1])
                if self.board.at(next_location,self.player):
                    result.extend(dirDelta)
            return result
            
        def makeBoard(self):
            result = copy.deepcopy(self.board)
            for location in self.discDelta:
                result.turnoverDisc(location)
            result.placeDisc(self.location,self.player)
            return result

    class ReversiTest(unittest.TestCase):
    
        def testMovePreviewWhite(self):
            board = Board()
            location = Location(4,5)
            move = Move(board,location,'W')        
            self.assertEquals([Location(4,4)], move.discDelta)
    
        def testMovePreviewBlack(self):
            board = Board()
            location = Location(3,2)
            move = Move(board,location,'W')        
            self.assertEquals([Location(3,3)], move.discDelta)
        
        def testMove(self):
            board = Board()
            expected_board = """
                |_|_|_|_|_|_|_|_|
                |_|_|_|_|_|_|_|_|
                |_|_|_|_|_|_|_|_|
                |_|_|_|B|W|_|_|_|
                |_|_|_|W|W|_|_|_|
                |_|_|_|_|W|_|_|_|
                |_|_|_|_|_|_|_|_|
                |_|_|_|_|_|_|_|_|
                """
            expected = Board(expected_board)
            location = Location(4,5)
            move = Move(board,location,'W') 
            result = move.makeBoard()
            self.assertEquals(expected, result)
            self.assertEquals(board, Board())
            self.assertEquals(location, Location(4,5))