3

I'm trying to port a C application to Python, and there are a lot of pointers. Are these equal:

obj->position = (float*) malloc(obj->totalItems * obj->xyz * sizeof (float));
for (i = 0; i < components; i++) {
    obj->comps[i].position = obj->position + obj->pOffset; // Pointer arithmetic
obj->pOffset += obj->comps[i].items * obj->xyz;
}

And

for i in range(self.totalItems * self.xyz):
    self.position.append(0.0)
for i in range(self.components):
    self.comps[i].position = self.position[self.pOffset:] # Position was a C pointer
    self.pOffset += self.comps[i].items * self.xyz

I know that Python objects are passed by reference, so I'm wondering if:

self.comps[N].position = [1,2,3,4]

will change some part of:

self.position[]
Richard Żak
  • 814
  • 1
  • 11
  • 21
  • 2
    google search for `python pointer` - 2nd result: http://mail.python.org/pipermail/edu-sig/2008-May/008531.html – SeanC Aug 02 '12 at 18:42
  • @SeanCheshire: you've linked to an excellent explanation. Here's another one [Other languages have variables, Python has names](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables) (with pictures this time) – jfs Aug 02 '12 at 21:28

2 Answers2

3

Maybe something like this:

self.position = [0.0 for _ in self.total_items * self.xyz]
for i in range(self.components):
    self.comps[i].position = self.p_offset
    self.p_offset += self.comps[i].items

In Python, you can change values inside a class instance variable. This is called "mutating" the instance. If the class doesn't allow this, it is an "immutable" class; if it does allow this, it is a "mutable" class. Strings are immutable, as are integers, but lists are mutable.

In Python, there is no way that I can think of to get a reference to the middle part of a list. Lists are mutable: things can be inserted, deleted, etc. What should the reference do then?

So instead of doing pointer math and storing a reference to a spot within a list, you should just store the offset, and then use the offset to index the list when you need to reference that spot in the list.

For your specific question:

self.comps[N].position = [1,2,3,4]

This would rebind the name position inside the self.comps[N] object to now point to a newly created list instance with the value [1, 2, 3, 4] and would not affect self.position at all. However, if you just set self.comps[i].position to index values you could use this code:

i = self.comps[N].position
lst = [1, 2, 3, 4]
self.position[i:i+len(lst)] = lst

This would use a "slice" into the self.position list to replace the values.

Note that if you use SciPy or even just NumPy, you can define a numpy.array which is not dynamic; and you can use "views" to get a reference to just part of the list. You might want to look into that, especially if you are working with really large arrays or matrices.

View onto a numpy array?

Community
  • 1
  • 1
steveha
  • 74,789
  • 21
  • 92
  • 117
1

self.comps[N].position = [1,2,3,4]

will set self.comps[N].position to be a new list. If there are other references to the old list that was self.comps[N].position, they will not be changed.

Example

x=[1,2,3]
y=x
print y #[1, 2, 3]
x[1]=4
print y #[1, 4, 3]
x=[4,5,6]
print y #[1, 4, 3]
Jason
  • 1,059
  • 9
  • 13