Newbie: question regarding references and class relationships

Rick Johnson rantingrickjohnson at gmail.com
Tue Jun 11 19:50:38 EDT 2013


On Monday, June 10, 2013 8:18:52 AM UTC-5, Rui Maciel wrote:
> [...]
>
> <code> 
> class Point:
>         position = []
>         def __init__(self, x, y, z = 0):
>                 self.position = [x, y, z]

Firstly. Why would you define a Point object that holds it's x,y,z values in a list attribute? Why not store them as self.x, self.y and self.z? But if you are going to store them as a list, then why not extend a python list? I hate to see a "listy" object that only holds a list. It begs the question: Why not make it a *real* list? (Although i believe the former approach is more desirable for this problem)

Secondly, why would store the position of the Point as a class attribute? Do you realize that EVERY instance of the Point object will share the same x,y, and z values if you do it that way? (considering you query the correct variable *evil grin*)

Actually, you have a legitimate excuse: you were fooled because in your "object definition" you declared a "class level variable" named "position". THEN in your "__init__" method you declared an "instance level variable" named "position". 

Then, when you assigned the x,y,z values to "self.position" you thought you where assigning them to the "class level variable" named "position", HaHa, but then again you had NO idea that "class level variables" and "instance level variables" even existed! (or, at least, how to properly declare them)

Q: Yes Rick but how do i solve this issue?

By changing the names we can inspect the Point object and understand how class level and instance level variables work in Python. Observe:

## START SESSION ##
py> class Foo(object):
...     classVar = []
...     def __init__(self, arg):
...         self.instanceVar = arg
... 
py> Foo.classVar
[]
py> Foo.classVar = "apple"
py> Foo.classVar
apple
py> foo1 = Foo("pear")
py> foo1.classVar
apple
py> foo1.instanceVar
pear
py> foo2 = Foo("peach")
py> foo2.classVar
apple
py> foo2.instanceVar
peach
## END SESSION ##

As you can see the "class level variable" is known to all instances of the object, and a change in one is equal to a change in all. Whereas the "instance level variables" are unique to each instance.

> class Line:
>         points = ()
>         def __init__(self, p_i, p_f):
>                 self.points = (p_i, p_f)

Same problem here with the class level/instance level thing.

> It would be nice if, whenever a Point object was updated,
> the Line objects which are associated with it could
> reflect those updates directly in Line.p_i and Line.p_f.
> What's the Python way of achieving the same effect? Thanks
> in advance, Rui Maciel
> 

If you construct your code properly this can be achieved. If each point is an object, and lines are merely holding references to two point objects that define the start and end position of an imaginary "line", then updates on the points will be reflected in the Line object. 

Observe:

## START SESSION ##
py> class Point3d(object):
...     def __init__(self, x, y, z):
...         self.x = x
...         self.y = y
...         self.z = z
...     def __str__(self):
...         _ = 'Point3d({}, {}, {})'
...         return _.format(self.x, self.y, self.z)
...         
py> p1 = Point3d(1,2,3)
py> str(p1)
Point3d(1, 2, 3)
py> p2 = Point3d(3,4,5)
py> str(p2)
Point3d(3, 4, 5)
py> class Line3d(object):
...     def __init__(self, p1, p2):
...         self.p1 = p1
...         self.p2 = p2
...     def __str__(self):
...         _ = 'Line3d({}, {})'
...         return _.format(self.p1, self.p2)
...         
py> line1 = Line3d(p1, p2)
py> str(line1)
Line3d(Point3d(1, 2, 3), Point3d(3, 4, 5))
py> p1.x = 100
py> str(p1)
Point3d(100, 2, 3)
py> str(line1)
Line3d(Point3d(100, 2, 3), Point3d(3, 4, 5))
## END SESSION ##

Easy peasy.



More information about the Python-list mailing list