Reputation: 135
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
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
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
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