0

I am looking for a way to implement an object as an array with different attributes in Python. My idea is an object-index looking like this:

self[row][col].item1 = True
self[row][col2].item2="xkcd"
...

I'm pretty sure I saw this before, however I can't recreate a class which allows this. My best call so far is (in dummy-code):

def __init__(self, posxy=[[...]*10]):
    self.posxy=posxy

which at least allows me to give the attribute posxy all informations I want. However I would strongly prefer the first variant. Could someone with more experience in object-oriented programming please help me out?

3 Answers 3

2

You want to look at the Emulating container types section of the Python datamodel.

At the very least, you'll have to implement the __getitem__ hook to let your class handle [...] indexing. This will only be pass the first row value, whatever this method returns will be indexed for [col].

You can choose to handle tuples instead, indexing on self[row, col] too, the key argument will then be passed a tuple of two values instead:

def __getitem__(self, key):
    row, col = key  # unpack the tuple
    return self.matrix[row][col]
Sign up to request clarification or add additional context in comments.

Comments

1

You can inherit from defaultdict to get something like this:

import collections

class MyClass(collections.defaultdict):
  def __init__(self):
    collections.defaultdict.__init__(self, dict)
    self[0][0] = True
    self[0][1] ="xkcd"

ie, each top-level index yields a dict. If you want something more structured, your defaultdict needs a different factory function ... maybe it yields a MyInnerClass which is also a defaultdict, containing your eventual type.

All defaultdict is doing for you is implementing __getitem__, __setitem__, __contains__ etc. See Martijn's link for the full list of methods, if you want to implement it by hand.

Comments

1

To use the [] notation you need to override the __getitem__ special method. A simple example:

class X:
    def __init__(self, data):
        self.data = data

    def __getitem__(self, index):
        return self.data[index]

So to have rows and columns you can try the following:

class Row:
    def __init__(self, data):
        self.data = data

    def __getitem__(self, index):
        return self.data[index]

class Matrix:
    def __init__(self, data):
        self.data = [Row(d) for d in data]

    def __getitem__(self, index):
        return self.data[index]

Simple demo:

class X:
    def __init__(self, value):
        self.item1 = value

x = Matrix([[X('11'), X('12'), X('13')], [X('21'), X('22'), X('23')]])

print x[1][1].item1

Gives:

>>>22

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.