0

I have an object which contains many of it's fields in a numpy array (they are all of type float64). Some of these fields have meaningful names that I would like to use when accessing/writing, but with my current knowledge, I have to access and write like this:

//access:
value = data[0]
//write:
data[0] = value

If I was working in C, I would do something like this:

#define fieldname data[0]
//access:
value = fieldname
//write:
fieldname = value

How can I do something just as clean in python?

EDIT: All of these fields must stay in the numpy array because they get updated by a linear transformation using numpy matrix operations.

EDIT: If I write this method:

def fieldname(self):
  return self.data[0]

my accesses look as desired, but I cannot write back to data in the same way.

//access:
value = self.fieldname

(self was omitted in the code before this because I felt the problem generalized to situations outside of objects.)

This post about overloading the assignment operator might be close to what I want: How to Emulate Assignment Operator Overloading in Python?

SOLUTION: Write __getattr__ and __setattr__ methods that take field names and do the necessary operations on self.data. These will not get called when the field name provided matches the field name of another attribute other than data, and add the functionality of getting stuff from data when names of these special attributes are provided.

Community
  • 1
  • 1
user1123936
  • 181
  • 3
  • 4
  • 14
  • There's not enough context to tell if this would work for you, but look into the NamedTuple class: http://docs.python.org/2/library/collections.html#namedtuple-factory-function-for-tuples-with-named-fields – Brenden Brown Jan 14 '13 at 19:28
  • That's not exactly the same since Python uses references, in this case to an immutable object. If the value of `data[0]` changed the value of `value` would not change. It would be whatever it was when first referenced. – Keith Jan 14 '13 at 19:33

2 Answers2

1

The first method you posted seems clean and sufficiently clear to me. Keep in mind that

value = data[0]

and

data[0] = value

are just syntactic sugar for

value = data.__getitem__(0)

and

data.__setitem__(0, value)

respectively.

If you really, really want to make row access more clear, consider defining constants for different field names.

FIELDNAME1, FIELDNAME2, FIELDNAME3 = range(3)

data[FIELDNAME1] = value

value = data[FIELDNAME2]
Joel Cornett
  • 24,192
  • 9
  • 66
  • 88
  • This will work just fine. I have to use field names for access because there are many fields, and it would be hard to remember which number each field was. – user1123936 Jan 14 '13 at 21:15
  • @user1123936: The fact is, python just doesn't do pointer arithmetic. You could bend over backwards (figuratively) and write something that works like a pointer, but I'd say that would be much more confusing than accessing values by their key/index as above. The equivalent python idiom is: "There should be one-- and preferably only one --obvious way to do it." – Joel Cornett Jan 14 '13 at 21:45
1

If you have descriptive lables for all your fields you can do an enum-like thing. Python doesn't have enums, but there are are numerous ways to do similar things, as discussed here: How can I represent an 'Enum' in Python?

For example, and at the risk of the usual enum debate, you could do something like:

def enum(**enums):
    return type('Enum', (), enums)

Numbers = enum(ONE=1, TWO=2, THREE='three')
print Numbers.ONE
print Numbers.TWO
print Numbers.THREE
Community
  • 1
  • 1
john hight
  • 91
  • 6
  • If I used this, it seems that my accesses would look like this: `value = data[Numbers.FIELDNAME]`, which isn't as nice as `value = data[FIELDNAME]`, in Joel Cornett's solution. – user1123936 Jan 14 '13 at 21:23
  • @user1123936: Actually I prefer this method, as it reduces namespace clutter. – Joel Cornett Jan 14 '13 at 21:46
  • I actually meant `data.ONE`, `data.TWO`, etc. But you and Joel Cornett are right. I withdraw my proposal. – john hight Jan 14 '13 at 22:01