|
![](/i/fill.gif) |
I'm trying to improve myself in this area. I use objects, but there are some
things I think I just haven't wrapped my head around. I don't personally know
any programmers, so my though process has evolved, for the most part, in
isolation.
OK, starting with the basics. I want to add two vectors. The OO way ...
(as I understand it. Please include "as I understand it" as a standard
disclaimer for anything I write here.)
..... is to make a vector object and define an addition method. My vector would
be
an instance of a Vector class. That would look like:
a = Vector(1, 2, 3)
b = Vector(4, 5, 6)
and I would add them together with
c = a.add(b)
Well, not if I want to keep my sanity, because nothing else in Python works that
way. In Python (and I assume every other language), things that look like
instance.method()
return None and change the state of instance. I don't want to return None OR
change the state of instance, but if I want to avoid bleeding from my eyeballs
in the future, I'd better make sure I stick to that convention. (Sure, there's
also a + b possible, but I want to expand this logic to more complex
operations).
So, I make a function and end up with
c = vector_addition([1, 2, 3], [4, 5, 6])
And then I realize that vector_addition is "good" for other things as well:
c = vector_addition(([1], [2], [3]], [[4], [5], [6]])
is an ugly, sloppy way to get the transverse of a 2xwhatever matrix.
And that could be improved. Instead of the ugly [[1], [2], [3]] stuff, I could
define another functions which add numbers like lists
list_addition(a, b) => [a, b]
Now I can use
c = vector_addition(number_addition, a, b)
or
c = vector_addition(list_addition, a, b)
or functools.partial into vector_like_list_addition(a, b)
And this all works out, because many times there will be no 'a' and 'b'. The
arguments will be used once and never assigned to a variable, much less
instanced into a user-defined class.
Actually that's most of the time. When I want the distance between a point and a
plane, I may have a point object, but I won't have a plane object. I'll just
have a bunch of other data that can be used to describe a plane. The only thing
I need to know about the plane is that it happens to be the plane one of my
triangles is sitting on. I don't need a plane, I need to treat a triangle like a
plane.
Or, there may be tens of thousands of 'a's and 'b's, and they'll be in a file
somewhere which doesn't require my importing an object definition.
So, my thinking is: sometimes I want to stack bricks like bricks, but it's often
handy to stack bricks like rocks or marbles or bananas. And if my banana_stack
function can't handle it, then I've probably poorly (not abstractly enough)
described my bricks.
I get(?) that this is what inheritance is for, but I feel like I'm forcing a
round peg through a square hole when I try it. I've made too many assumptions
before I get to implementation. I'm trying to look at these problems in a
different way FROM THE BEGINNING.
Not every problem can be solved as elegantly as the one above, so I try to use
OO, but my classes turn into monsters. My objects have attributes which are
objects themselves, which have their own attributes which ...
I end up with
A.attr.attr = A.attr.attr.method(A.attr.attr.attr.method(arg))
From the above, it's obvious I'm breaking the instance.method()=>None convention
as well. If I don't, I end up with a module full of object-specific functions
and an object that doesn't do much more than a dictionary. I could do a cleaner
job with an actual dictionary or struct-like class, but I'm /trying/ to learn.
Guidance welcome.
-Shay
Post a reply to this message
|
![](/i/fill.gif) |