Question

There are similar questions on Stack Overflow, but I cannot find what I am doing wrong in my code.

def copyPic():
  file=pickAFile()
  oldPic=makePicture(file)
  newPic=makeEmptyPicture(getWidth(oldPic),getHeight(oldPic))
  for y in range(0,getHeight(oldPic)):
    for x in range(0,getWidth(oldPic)):
      oldPixel=getPixel(oldPic,x,y)
      colour=getColor(oldPixel)
      newPixel=getPixel(newPic,x,y)
      setColor(newPixel,colour)
explore(newPic)

When I use explore(newPic) or show(newPic) outside of the function, gives a blank white canvas.

Is this because the newPic is not saved? How do I 'save' the changes to newPic?

Was it helpful?

Solution

It is a matter of scope of the variable :

When you define a function (here copyPic()) all the variables created inside this function are "visible" by the function only. The global program does not know anything about its existence.

The Python interpreter reads the code in the order it is written (sequentially). As newPic is defined in the function in the first place, it belong to it and is destroyed once the function terminates. That is why you can't refer to newPic afterward. To fix this you have to return the variable (keyword return) such that you can get it from the main program when calling the copyPic() function.

You have to do as follows :

def copyPic():
  file=pickAFile()
  oldPic=makePicture(file)
  newPic=makeEmptyPicture(getWidth(oldPic),getHeight(oldPic))
  for y in range(0,getHeight(oldPic)):
    for x in range(0,getWidth(oldPic)):
      oldPixel=getPixel(oldPic,x,y)
      colour=getColor(oldPixel)
      newPixel=getPixel(newPic,y,x)
      setColor(newPixel,colour)

  return newPic      # HERE IS THE IMPORTANT THING

newPic = copyPic()   # Here we assign the returned value to a new variable
                     # which belong to the "global scope".
explore(newPic)

Note : Here, I used 2 variables called identically newPic. Those are considered as two different variables by the Jython Interpreter :

  • The first one belongs to the function (function scope)
  • The second one belongs to the main program (also called global scope)

Thus the code above is exactly equivalent to this one :

def copyPic():
  file=pickAFile()
  ...
  return newPic    

newPic_2 = copyPic()    # Here we store / assign the "newPic" returned by the 
                        # copy function into another variable "newPic_2" (which
                        # is a "global variable").
explore(newPic_2)



EDIT :

An alternative to all of this would have been to use the global keyword to tell the interpreter that newPic was to be found from the global scope :

newPic = None           # First declare "newPic" globally.

def copyPic():
  global newPic         # Tell the function to refer to the global variable.
  ...
  #return newPic        # No need to return anything, the function is 
                        # modifying the right variable.

copyPic()
explore(newPic)

Note that generally speaking, one try to avoid using global variables. There is always better designs, specially with Python which is clearly object oriented...


I hope I made myself clear. If not, do not hesitate to ask further explanations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top