简体   繁体   中英

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!

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

then call it

some_cell.my_idx(grid)

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.

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. ;-)

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.

Give your cell class an address attribute, which is a two-tuple, eg (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 cell s need to know and/or do, but if you're just doing numerical stuff here, I'd highly recommend the scipy.sparse module.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM