Hackpact Day 8: Refactoring, classes and operators

I’ve been improving my canvas app these days but I didn’t have time to blog about it, sorry, thats the reason why I’m a few days behind. Mainly because most of the work done is not really interesting, it is more about refactoring my old code, arranging it in a more clever way, and dealing with stupid problems.

I have improved the way the brushes behave, I created new brushes, and solve some bugs.

The only interesting thing I did was to create a Vector class, the common class you use to store the coordinates of a point. I overwrited all the operators so now is transparent to use the class, it behaves more like a list, but you can multiply it or divide it, operate between Vectors, etc.

That task is kind of fustrating, when you are an experienced C++ programmer and you jump to a high level language like python you always miss some of the low level part of programming. For instance, in python if I have an instance in A and I do “B = A” then A and B share the same instance, so vars behave more like pointers.

That is a big source of bugs, because most of the times I dont realize python don’t do copies unless you say it explicitly, and I have several vars sharing the same instance. So now I tend to solve the problem having an option in the constructor of a class that receives an instance. So I can do:

a = vec([10,10])

b = vec(a) # this is a copy

All the information you need about OOP in python is on the internet, so that is not a big problem. But to code the class Vector was more like a test, because I will end up using the CG library I wrote about some posts ago, I don’t like to have more dependencies but I don’t want to code all those low level maths, more when I hardly know how to make efficient functions.

Here is my Vector class, it can be used for 2,3,4,or N dimension vectors, and you can use it where the app expects a list and it wont crash:

from copy import copy
from math import *

class vec:
    def __init__(self,v=[0.0,0.0]):
        if type(v) == list:
            self.data=v
        elif type(v) == tuple:
            self.data=list(v)
        elif v.__class__.__name__== self.__class__.__name__:
            self.data = copy(v.data)
        else:
            raise Exception("Wrong parameter type:" + str( type(v)) )

    def __repr__(self):
        s = "vec("
        for a in self.data: s += "%0.3f,"%a
        return s[:-1] + ")"

    def toList(self):
        return copy(v.data)

    # overload []
    def __getitem__(self, index):
        return self.data[index]

    # overload set []
    def __setitem__(self, key, item):
        self.data[key] = item

    def __add__(self, other):
        return vec( map(lambda a,b:a+b,self,other) ) #[self.data[0] + other.data[0],self.data[1] + other.data[1]] )

    def __sub__(self, other):
        return vec( map(lambda a,b:a-b,self,other) )

    def __mul__(self, other):
        if type(other) == int or type(other) == float:
            return vec( map(lambda a:a*other,self) )
        else:
            return vec( map(lambda a,b:a*b,self,other) )

    def __div__(self, other):
        if type(other) == int or type(other) == float:
            return vec( map(lambda a:a/float(other),self) )
        else:
            return vec( map(lambda a,b:a/float(b),self,other) )

    # return size to len()
    def __len__(self):
            return len(self.data)

    def copy(self,v):
        self.data = copy(v.data)

    def module(self):
        return sqrt(sum(map(lambda a: a*a,self.data) )  )

    def distance(self,b):
        return (b-self).module()

Today there is no screenshots or code, sorry, but check the next post.

Leave a Reply


× 4 = eight