2

I'm writing a Python program to play Tic Tac Toe, using Numpy arrays with "X" represented by 1 and "O" by 0. The class includes a function to place a mark on the board:

import numpy as np

class Board():
    def __init__(self, grid = np.ones((3,3))*np.nan):
        self.grid = grid

    def place_mark(self, pos, mark):
        self.grid[pos[0],pos[1]] = mark

so that, for example,

board = Board()
board.place_mark([0,1], 1)
print board.grid

yields

[[ nan   1.  nan]
 [ nan  nan  nan]
 [ nan  nan  nan]]

I was wondering if the pos[0], pos[1] argument in the place_mark function could somehow be replaced by the 'unpacked' contents of pos (which is always a list of length 2). In Ruby this would be done using the splat operator: *pos, but this does not appear to be valid syntax in Python.

Dartmouth
  • 1,069
  • 2
  • 15
  • 22
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526

2 Answers2

3

With Numpy, there's a difference between indexing with lists and multi-dimensional indexing. self.grid[[0,1]] is equivalent to concatenating self.grid[0] and self.grid[1], each 3x1 arrays, into a 3x2 array.

If you use tuples instead of lists for indexing, then it will be correctly interpreted as multi-dimensional indexing: self.grid[(0, 1)] is interpreted the same as self.grid[0, 1].

There is a * operator for unpacking sequences, but in the context of function arguments only, at least in Python 2. So, with lists you could also do this:

def place_mark(self, mark, x, y):
    self.grid[x, y] = mark

place_mark(1, *[0, 1])

NB. (Expanded usefulness of * in Python 3)

ptomato
  • 56,175
  • 13
  • 112
  • 165
2

As suggested by Lukasz, the input argument should be a tuple. In this example it can be converted to one:

def place_mark(self, pos, mark):
    self.grid[tuple(pos)] = mark

My question is not the same What is the pythonic way to unpack tuples? because pos does not constitute the input arguments to a function, but rather the indices of a 2-dimensional array.

Community
  • 1
  • 1
Kurt Peek
  • 52,165
  • 91
  • 301
  • 526