# PVectors in Class Objects

**URL:** <https://discourse.processing.org/t/pvectors-in-class-objects/40697>\
**Category:** Processing.py\
**Created:** [January 24, 2023, 9:41pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697 "2023-01-24T21:41:19Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![SailorMike](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/sailormike/32/17857_2.png) [@SailorMike](https://discourse.processing.org/u/SailorMike)\
**Post date:** [January 24, 2023, 9:41pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/1 "2023-01-24T21:41:19Z")

</div>

I’m hoping someone can explain this to me, as I’m pretty new to this stuff. Here’s a program that shows the problem I’m having:

targ\_pos = PVector(100, 300, 0)  
mis\_pos = PVector(400, 600, 0)  
l\_o\_s = PVector()

class Foo:  
def **init** (self, targ\_pos, mis\_pos):  
self.targ\_pos = targ\_pos  
self.mis\_pos = mis\_pos  
self.l\_o\_s = PVector()  
def sub\_vec(self, target\_pos):  
# temp\_vec = mis\_pos.copy() # uncomment to clear error  
# self.l\_o\_s = temp\_vec.sub(self.targ\_pos) # uncomment to clear error  
self.l\_o\_s = self.mis\_pos.sub(self.targ\_pos) # comment to clear error  
return self.l\_o\_s

foo = Foo(targ\_pos, mis\_pos)  
i = 1

def draw():  
global i  
vec = foo.sub\_vec(targ\_pos)  
print('targ\_pos ', targ\_pos)  
print('mis\_pos ', mis\_pos)  
print('vec ', vec)  
if i == 2:  
noLoop()  
i += 1

The output looks like this:  
('targ\_pos ', [100.0, 300.0, 0.0])  
('mis\_pos ', [300.0, 300.0, 0.0])  
('vec ', [300.0, 300.0, 0.0])  
('targ\_pos ', [100.0, 300.0, 0.0])  
('mis\_pos ', [200.0, 0.0, 0.0])  
('vec ', [200.0, 0.0, 0.0])

The PVector ‘mis\_pos’ is changing, though there is no instruction that would cause it to do so. If I make a copy of that vector and use the copy for the subtraction, it works as intended.

Any help appreciated, thanks, Mike

---

<div class="post-metadata">

**Author:** ![SailorMike](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/sailormike/32/17857_2.png) [@SailorMike](https://discourse.processing.org/u/SailorMike)\
**Post date:** [January 24, 2023, 9:53pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/2 "2023-01-24T21:53:48Z")

</div>

My apologies, I just learned that I should have formatted the code to make it easier to run.

```auto
targ_pos = PVector(100, 300, 0)
mis_pos = PVector(400, 600, 0)
l_o_s = PVector()

class Foo:
    def __init__ (self, targ_pos, mis_pos):
        self.targ_pos = targ_pos
        self.mis_pos = mis_pos
        self.l_o_s = PVector()
    def sub_vec(self, targ_pos):
        # temp_vec = mis_pos.copy() # uncomment to clear error
        # self.l_o_s = temp_vec.sub(self.targ_pos) # uncomment to clear error
        self.l_o_s = self.mis_pos.sub(self.targ_pos) # comment to clear error
        return self.l_o_s

foo = Foo(targ_pos, mis_pos)
i = 1    

def draw():
    global i
    vec = foo.sub_vec(targ_pos)
    print('targ_pos ', targ_pos)
    print('mis_pos ', mis_pos)
    print('vec ', vec)
    if i == 2:
        noLoop()
    i += 1

```

Mike

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [January 24, 2023, 10:56pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/3 "2023-01-24T22:56:52Z")

</div>

> [@SailorMike](#):
>
> If I make a copy of that vector and use the copy for the subtraction, it works as intended.

When we have a variable assignment, for example this 1: `targ_pos = PVector(100, 300, 0)`

What is actually stored in the variable is the memory address (a.K.a. reference or pointer) of an object.

If we have more than 1 variable, property or container assigned to the same reference value from another, they all become alias to the same object.

In order to avoid aliased variables, make sure to clone an object before assigning it.

For PVector, its methods **copy()** or **get()** will create a clone of it:

> **[copy() / Reference](https://processing.org/reference/PVector_copy_.html)**
>
> Copies the components of the vector and returns the result as a PVector.

For convenience, do it right there inside the constructor:

```auto
class Foo:
    def __init__ (self, targ_pos, mis_pos):
        self.targ_pos = targ_pos.get()
        self.mis_pos = mis_pos.get()
        self.l_o_s = PVector()

```

---

<div class="post-metadata">

**Author:** ![SailorMike](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/sailormike/32/17857_2.png) [@SailorMike](https://discourse.processing.org/u/SailorMike)\
**Post date:** [January 25, 2023, 12:03am UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/4 "2023-01-25T00:03:20Z")

</div>

Thanks for the reply, I thought it might be something to that effect. If you look at the code I posted, you’ll see ‘temp\_vec’ making a copy, which, when uncommented,.made it work fine. I’ll try the method you recommended and see how it goes.  
As I understand your reply, when I referenced a subtraction from the original vector, the result of the subtraction was stored in the original vector. I’ll have to chew on that for a bit, but I think I see what you mean.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [January 25, 2023, 12:20am UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/5 "2023-01-25T00:20:08Z")

</div>

> [@SailorMike](#):
>
> , the result of the subtraction was stored in the original vector.

Method **sub()** mutates the object invoking it.

As an alternative, use its static version [PVector](https://py.processing.org/reference/PVector.html).[**sub()**](https://py.processing.org/reference/PVector_sub.html) w/ 2 or 3 parameters.

---

<div class="post-metadata">

**Author:** ![SailorMike](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/sailormike/32/17857_2.png) [@SailorMike](https://discourse.processing.org/u/SailorMike)\
**Post date:** [January 25, 2023, 8:05pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/6 "2023-01-25T20:05:19Z")

</div>

Thanks, that did it! As the ‘sub\_vec’ method is called once per frame, that’s where I put the static method, rather than ‘ **init** ’. Here’s the code that works as intended:

```auto
class Foo:
    def __init__ (self, targ_pos, mis_pos):
        self.targ_pos = targ_pos
        self.mis_pos = mis_pos
        self.l_o_s = PVector()
    def sub_vec(self, target_pos):
        # temp_vec = mis_pos.copy() # uncomment to clear error
        # self.l_o_s = temp_vec.sub(self.targ_pos) # uncomment to clear error
        # self.l_o_s = self.mis_pos.sub(self.targ_pos) # commented to try static PVector
        self.l_o_s = PVector.sub(self.mis_pos,(self.targ_pos)) 
        return self.l_o_s

foo = Foo(targ_pos, mis_pos)

def draw():
    global i
    vec = foo.sub_vec(targ_pos)
    print('targ_pos ', targ_pos)
    print('mis_pos ', mis_pos)
    print('vec ', vec)

```

Your reply led me to Prof Schiffman’s excellent tutorial, which helped me a lot.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [January 25, 2023, 9:16pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/7 "2023-01-25T21:16:36Z")

</div>

> [@SailorMike](#):
>
> , that’s where I put the static method, rather than ‘ **init** ’.

I believe you didn’t grasp the reason I’ve advised you about cloning the passed PVector arguments inside **` __init__ ()`**.

The idea is once we’ve got a clone of each passed object argument we don’t have to worry about inadvertently modifying them anymore.

Take a look at this sketch example based on yours:

```auto
class Foo:
    def __init__ (self, targ_pos, mis_pos):
        self.targ_pos = targ_pos.get()
        self.mis_pos = mis_pos.copy()

    def sub_vec(self):
        self.mis_pos.sub(self.targ_pos)
        return self

    def __str__ (self, INFO = 'Foo { targ_pos: %s, mis_pos: %s }'):
        return INFO % (self.targ_pos, self.mis_pos)

targ_pos = PVector(100, 300, 0)
mis_pos = PVector(400, 600, 0)

foo = Foo(targ_pos, mis_pos)

def setup(FPS = .5): frameRate(FPS);

def draw(LOOPS = 4, INFO = 'Ori { targ_pos: %s, mis_pos: %s }\n'):
    background(int(random(PImage.ALPHA_MASK)))

    print foo.sub_vec()
    print INFO % (targ_pos, mis_pos)

    frameCount is LOOPS and noLoop()

```

And this is its log output:

```auto

Foo { targ_pos: [100.0, 300.0, 0.0], mis_pos: [300.0, 300.0, 0.0] }
Ori { targ_pos: [100.0, 300.0, 0.0], mis_pos: [400.0, 600.0, 0.0] }

Foo { targ_pos: [100.0, 300.0, 0.0], mis_pos: [200.0, 0.0, 0.0] }
Ori { targ_pos: [100.0, 300.0, 0.0], mis_pos: [400.0, 600.0, 0.0] }

Foo { targ_pos: [100.0, 300.0, 0.0], mis_pos: [100.0, -300.0, 0.0] }
Ori { targ_pos: [100.0, 300.0, 0.0], mis_pos: [400.0, 600.0, 0.0] }

Foo { targ_pos: [100.0, 300.0, 0.0], mis_pos: [0.0, -600.0, 0.0] }
Ori { targ_pos: [100.0, 300.0, 0.0], mis_pos: [400.0, 600.0, 0.0] }

```

Notice that even though property _mis\_pos_ is being mutated inside method **sub\_vec()**: `self.mis_pos.sub(self.targ_pos)`

The original global _mis\_pos_ keeps its original initial value of: `[400.0, 600.0, 0.0]`

In short, both properties _targ\_pos_ & _mis\_pos_ can be mutated w/o modifying the original passed parameters, b/c the former are clones of the latter, via methods **get()** or **copy()**:

```auto
def __init__ (self, targ_pos, mis_pos):
    self.targ_pos = targ_pos.get()
    self.mis_pos = mis_pos.copy()

```

---

<div class="post-metadata">

**Author:** ![SailorMike](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/sailormike/32/17857_2.png) [@SailorMike](https://discourse.processing.org/u/SailorMike)\
**Post date:** [January 25, 2023, 11:24pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/8 "2023-01-25T23:24:11Z")

</div>

So, as I understand it, the first two statements in ‘init’ do essentially the same thing, make a clone of the vectors involved. I’m unable to find a difference between ‘get’ and ‘copy’.

> [@GoToLoop](#):
>
> ```auto
> def sub_vec(self):
> self.mis_pos.sub(self.targ_pos)
> return self
> 
> ```

I assumed that the subtraction here would decrement ‘mis\_pos’, as it did before. Do the clones become immutable?  
BTW, your example showed me some unfamiliar programming features which I’ve figured out and no doubt will find useful in the future. Thanks for that.  
I appreciate your patience.  
Mike

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [January 25, 2023, 11:35pm UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/9 "2023-01-25T23:35:05Z")

</div>

> [@SailorMike](#):
>
> I’m unable to find a difference between ‘get’ and ‘copy’.

Methods **get()** & **copy()** from class PVector do the same clone action when invoked w/ no argument.

> [@SailorMike](#):
>
> Do the clones become immutable?

Nope! Clones are different objects initialized w/ the same content as the original object.

B/c a cloned object is separated from the original, we can mutate the content of either independently w/o affecting the content of the other.

Take notice that each object has its own memory address (a.K.a. pointer or reference), even if they happen to belong to the same class w/ exact same content.

---

<div class="post-metadata">

**Author:** ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)\
**Post date:** [January 26, 2023, 12:06am UTC](https://discourse.processing.org/t/pvectors-in-class-objects/40697/10 "2023-01-26T00:06:13Z")

</div>

The example bellow explains alias & clone w/ more detail:

```python
a = PVector.random2D(this) # new PVector object w/ random content
b = a # variable b is an alias of a, b/c they both refer to the same object
c = a.get() # variable c is a clone of a w/ exact same initial content

print a, b, c

print a == b, a == c, b == c # True True True
print a is b, a is c, b is c # True False False

b.div(2) # mutating b also mutates its alias a w/o affecting c
print a, b, c

c.sub(b) # mutating c won't affect either a or b
print a, b, c

exit()

```

Notice operator `==` checks content equality while `is` checks identity (memory address).
