Guye Incognito
Guye Incognito

Reputation: 2830

python, dictionary value is object, can that object access its own key value from a function within itself?

I'm using a dictionary in python to make what is basically an infinite 2d array by using a tuple as the key

grid = {}
grid[(0,0)] = cell()

the value 'cell' is a new object. Can I have, say, a function within that object that is able to get its key value? ie. (0,0)

I could just put that data in the object itself but then I'd have it existing twice which seems like bad programming. Thanks!

Upvotes: 0

Views: 723

Answers (5)

John Vinyard
John Vinyard

Reputation: 13495

Give your cell class an address attribute, which is a two-tuple, e.g. (0,0). Give the cell class a __hash__ method, which returns hash(self.address).

class cell:
    def __init__(self,address):
        self.address = address

    def __hash__(self):
        return hash(self.address)

    def __eq__(self):
        return hash(self) == hash(other)

You can still access cells by their address, but the cells know where they belong.

>>> c = cell((0,0))
>>> c
<so.cell instance at 0xb74c6a2c>
>>> grid = dict()
>>> grid[c] = c
>>> grid[c]
<so.cell instance at 0xb74c6a2c>
>>> grid[(0,0)]
<so.cell instance at 0xb74c6a2c>

I'm not sure what else your cells need to know and/or do, but if you're just doing numerical stuff here, I'd highly recommend the scipy.sparse module.

Upvotes: 0

Joran Beasley
Joran Beasley

Reputation: 113988

class cell(object):
     def my_idx(self,grid):
         return grid.keys()[grid.values().index(self)]

then call it

some_cell.my_idx(grid)

Upvotes: 1

Philip
Philip

Reputation: 1532

There are two separate issues here... first, to access the grid from within cell, I would have cell's constructor take a reference to grid as a mandatory argument.

grid = {}
grid[(0,0)] = cell(grid)

and

class cell:
  def __init__(self, gridRef):
    self.grid = gridRef

But, accessing the key is more challenging. One reason is that a dictionary is not a one-to-one mapping, so the same cell object may have multiple keys in your dictionary. You'd need to iterate over your keys and look for it, either manually or through flipping the dictionary. How about making your cell constructor take the key as well?

grid = {}
grid[(0,0)] = cell(grid, (0,0))

If that's too redundant, then maybe something like this?

def addToGrid(myDict, myCell):
  myDict[myCell.key()] = myCell

and then...

grid = {}
addToGrid(grid, cell(grid, (0, 0)))

where your cell class takes the dictionary key as the second argument and returns it via the key() method.

Upvotes: 1

Achim
Achim

Reputation: 15702

Your questions implies that there's a 1:1 mapping between dict keys and their values, which is not true. Take this code:

grid = {}
c = cell()
grid[(0,0)] = c
grid[(0,1)] = c

That's perfectly valid in python, even if your use case does not allow it. What index should the function you are looking for return for c?

Storing the data twice does not have to be bad programming style, but your memory might be limited. If your cell needs to know it's index, it must have that data. If you see your cells as a list of items, the dict becomes just a index for faster access. And having indexes for faster access is of course no bad programming style. ;-)

Upvotes: 1

Facundo Casco
Facundo Casco

Reputation: 10585

This should work:

class Cell(object):

    def get_idx(self, grid):
        """
        >>> cell = Cell()
        >>> cell.get_idx({(0, 0): cell})
        (0, 0)

        >>> cell = Cell()
        >>> cell.get_idx({(0, 0): Cell(), (1, 1): cell, (2, 2): Cell()})
        (1, 1)
        """
        return [x[0] for x in grid.items() if x[1] == self][0]

Just notice that it won't give you realiable results if the object is more than once in the dict and it would raise an exception if the object isn't in the dict.

Also it could be slow on very large grids.

Upvotes: 1

Related Questions