[Bf-python] CurNurb/IpoCurve/BezTriple hackery

Ken Hughes khughes at pacific.edu
Sat Jun 18 19:57:42 CEST 2005


Stephen Swaney wrote:
> On Sat, Jun 18, 2005 at 09:23:34AM -0700, Ken Hughes wrote:
> 
> 
>>But if the underlying object is changed, you don't expect for
>>Python to scribble to memory.  Iterators make it harder to do but
>>not impossible:
>>
>>  l=[]
>>  for p in some_ipo_curve:
>>     l.append(p)
>>
>>  some_ipo_curve.addBezier([1,2])
>>  l[0].setPoint([3,4])	# writes to freed memory
>>
>>
> 
>>True.... bad example on my part.  But
>>
>>  a = Blender.Ipo.Get('ObIpo')
>>  b = a.getCurve('LocX')
>>  a.delCurve('LocX')
>>  b.setInterpolation('Constant') # accesses freed memory
>>
>>is the same type of problem.
> 
> I would argue that both these examples are bad programming practice.
> Managing object lifetime is a critical part of Object Oriented 
> programming.

No argument here; they're not good code.  But in
Python I would expect this to throw an exception.

> What you are doing here is getting a reference to an object 
> ( a sequence in this case ) and then modifying the object
> by adding or deleting elements.  At that point, the reference
> you are holding is invalid.

But the reference to the object I'm changing isn't invalid;
if I call getPoints() -- or use the iterator on the object --
I get a valid sequence.  It's the same as this:

   a=[1,2,3]
   b=a
   for p in b:
      print p
   a.append(4)
   for p in b:
      print p

a.append(4) modifies object b as well, so the second loop
now prints "1 2 3 4", but b is still what it's supposed to
be: it's a copy of a.  If I choose to do "b=copy.copy(a)"
then it also does what it's supposed to: b doesn't change
when I do a.append() because I made sure it wouldn't do
that.

My point is that I can't come up with an example in Python
which does what the thin wrappers are doing here: where a
change in one object invalidates another.

What I'm expecting to happen in the case of Ipocurves and
bezTriples is something like this (think of a representing
the Ipocurve and its list of bezTriples, and b representing
one bezTriple)

 >>> a=[[1,2,3],[4,5]]
 >>> print a
[[1, 2, 3], [4, 5]]
 >>> b=a[0]
 >>> print b
[1, 2, 3]
 >>> a[0][0]=7
 >>> print a
[[7, 2, 3], [4, 5]]
 >>> print b
[7, 2, 3]
 >>>>>> a.pop(0)
[7, 2, 3]
 >>> print a
[[4, 5]]
 >>> print b
[7, 2, 3]
 >>>

If you change the bezTriple object or an item in the Ipocurve's
sequence of bezTriples, both objects reflect the change because
they refer to the same object.  However, if you change the Ipocurve
list, the bezTriple object is still valid (it no longer has anything
to do with the Ipocurve, true, but it's a reference to an existing
Python object).

> You can do the same thing is C by allocating an array and
> setting another pointer to it.  If you then realloc the
> array, the held pointer is probably not valid.

Yes, but C isn't OO; it easy for a programmer to do things which
will corrupt memory.   Python should be better than that.

Ken



More information about the Bf-python mailing list