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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.