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.