NN314
NN314

Reputation: 135

How to create objects with array-properties in Python

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?

Upvotes: 0

Views: 638

Answers (3)

BartoszKP
BartoszKP

Reputation: 35891

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

Upvotes: 1

Useless
Useless

Reputation: 67713

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.

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1121406

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]

Upvotes: 2

Related Questions