Good question. 
Using functions is a good start in making your code neater. Classes are a neat way of going a little further with that by grouping together functions and variables (aka attributes) that have some logical connection.
Classes essential define a type of object and if it makes sense to think of your thing as an object then you probably want a class. For instance the psychopy Window
is a class and it has various methods (functions) like draw()
but stores various attributes, like its background color and its size, the id of the window in the operating system etc, all of which it needs to know about to perform its functions. The other great thing with a class is that you can store it in your own file of python tools and reuse it at will. (That’s essentially what the psychopy library is)
How about a concrete example. Well, let’s say you want a fixation point that stands out in front of a photographic image. You could have white dot, sitting on a black dot sitting on a grey dot.
With no function at all you could do:
# top of script
fixWhite = visual.Circle(win, size=5, units='pix', color='grey')
fixBlack = visual.Circle(win, size=7, units='pix', color='black')
fixGrey = visual.Circle(win, size=10, units='pix', color='grey')
# each time you draw fixation
fixGrey.draw()
fixBlack.draw()
fixWhite.draw()
##Using a function
Those three lines of drawing would occur quite often and would be neater as a function so you’d have:
# top of script
fixWhite = visual.Circle(win, size=5, units='pix', color='grey')
fixBlack = visual.Circle(win, size=7, units='pix', color='black')
fixGrey = visual.Circle(win, size=10, units='pix', color='grey')
# create func
def drawFix():
fixGrey.draw()
fixBlack.draw()
fixWhite.draw()
# re-use during script
drawFix()
##Make a class
The class approach allows you to store your ring objects and also handle the drawing method (and potentially others)
class FixationRings:
def __init__(self, win, color1, color2, color3):
self.ring1 = visual.Circle(win, size=5, units='pix', color=color1)
self.ring2 = visual.Circle(win, size=7, units='pix', color=color1)
self.ring3 = visual.Circle(win, size=10, units='pix', color=color1)
def draw(self):
self.ring1.draw()
self.ring2.draw()
self.ring3.draw()
#create an instance of that object/class
fix = FixationRings(win, 'white', 'black', 'grey')
fix.draw() # as needed
Re-use your class
The last step in writing re-usable code is that you move the definition of your class into a separate file that all your experiments can see (added to the python path) so that in your script you just have:
from psychopy import visual
import mytools
win = visual.Window([80,600])
fix = mytools.FixationRings(win, 'white','black','grey')
fix.draw()
win.flip()