[Python-Dev] turtle.Screen.__init__ issue

Gregor Lingl gregor.lingl at aon.at
Mon Sep 22 00:15:36 CEST 2008


Hello there,

its high time to resolve an issue, which I have already addressed twice 
some weeks ago. (You can find a more elaborate description in my former 
posting cited below)

There is a tiny difference (also in behaviour!) in 
turtle.Screen.__init__() between the versions for 2.6 and 3.0. The 
difference results from the fact, that I submitted the 3.0 version 
approx. a week later, after having it ported to 3.0. In this process I 
had found what I now consider to be a bug in 2.6 and changed it 
accordingly.  Shortly:

If you have already a Screen object containing some turtles and some 
graphics,

in 2.6: s = Screen() returns an object with identical state and 
behaviour, but clears (re-initializes) the screen and thus destroys the 
content
in 3.0 s = Screen()  returns an object with identical state and 
behaviour, but leaves the content untouched

The difference in code consist only in indenting the call of the 
__init__ method of the parent class, so it will be executed only 
conditionally.

Anyway, as this difference between the two versions is highly 
undesirable there are (imho) three options to proceed:

(1) correct 2.6 in order that it will work like 3.0
(2) undo the change in 3.0 in order that it will work like 2.6
(3) find a different solution for both

I would (like Vern, see below) decisevely prefer option (1), and I 
suppose that there is not enough time left to chose option (3) as this 
would probably need some discussions.

What is your opinion, and who should decide?

For your convenience I've attached a diff-file which also contains the 
description of three other small bugs, which I've found in the meantime 
and which shouldn't cause any controversies.

Regards, Gregor


%%%%%%%%%%

Here follows the answer of Vern Ceder - a long term turtle graphics user 
and author of several patches for the old turtle module - to my former 
posting:

 >> Gregor,
 >>
 >> I don't feel authoritative on the correctness/appropriateness of the 
implementation,
 >> but I do agree completely that behavior b, or what you have in the 
3.0 version,
 >> is vastly preferable.
 >>
 >> Cheers,
 >> Vern



-------- Original-Nachricht --------
Betreff: 	[Python-Dev] turtle.Screen- how to implement best a Singleton
Datum: 	Mon, 18 Aug 2008 10:15:45 +0200
Von: 	Gregor Lingl <gregor.lingl at aon.at>
An: 	python-dev at python.org
CC: 	Toby Donaldson <tjd at sfu.ca>, python-3000 at python.org, 
jjposner at snet.net, Brad Miller <bonelake at gmail.com>, Vern Ceder 
<vceder at canterburyschool.org>



Hi,

this posting - concerning the new turtle module - goes to the Python-Dev 
and Python-3000 lists and to a couple of 'power users' of turtle 
graphics, hoping to recieve feedback from the developer's point of view 
as well as from the user's point of view.

Currently the implementations of the turtle.Screen class for Python 2.6 
and Python 3.0 differ by a 'tiny' detail with an important difference in 
behaviour. So clearly this has to be resolved  before the final 
release.(The origin of this difference is, that when I ported turtle.py 
to Python 3.0 I discovered (and 'fixed') what I now consider to be a bug 
in the 2.6 version.) I'd like to ask you kindly for your advice to 
achieve an optimal solution.

The posting consists of three parts:
1. Exposition of design goals
2. Problem with the implementation 
3. How to solve it?

Preliminary remark:  I've had some discussions on this topic before but 
I still do not see a clear solution. Moreover I'm well aware of the fact 
that using the Singleton pattern is controversial. So ...

1. Exposition of design goals
... why use the Singleton design pattern? The turtle module contains a 
TurtleScreen class, which implements methods to control the drawing area 
the turtle is (turtles are) drawing on. It's constructor needs a Tkinter 
Canvas as argument. In order to avoid the need for users to tinker 
around with Tkinter stuff there is the Screen(TurtleScreen) class, 
designed to be used by beginners(students, kids,...), particularly in 
interactive sessions.

A (THE (!)) Screen object is essentially a window containing a scrolled 
canvas, the TurtleScreen. So it's a ressource which should exist only 
once. It can be constructed in several ways:
- implicitely by calling an arbitrary function derived from a 
Turtle-method, such as forward(100) or by constructing a Turtle such as 
bob = Turtle()
- implicitely by calling an arbitrary function derived from a Screen 
method, such as bgcolor("red")
- explicitely by calling it's constructor such as s = Screen()
Anyway this construction should only happen if a Screen object doesn't 
exist yet.
Now for the pending question: What should happen, when s = Screen() is 
called explicitely and there exists already 'the' Screen object.
(i) Clearly s should get a reference to the existing Screen object, but ...
(ii) (a)... should s be reinitialized (this is the case now in Python 
2.6), or
    (b)... should s be left untouched (this is the case now in Python 3.0)

I, for my part, prefer the latter solution (b). Example: a student, 
having (interactively) produced some design using some turtle t = 
Turtle() decides spontaneously to change backgroundcolor. s = Screen(); 
s.bgcolor("pink") should do this for her - instead of deleting her 
design and moreover her turtle. To reinitialize the screen she still can 
use s.clear().

Of course, there are workarounds to achieve the same effect also with 
solution (a), for instance by assigning s = Screen() *before* drawing 
anything or by assigning s = t.getscreen(). But imho (which derives 
itself from my experience as a teacher) solution (b) supports better the 
oop-view as well as experimenting spontaneously in interactive sessions.

2. Problem with the implementation
The task is to derive a Singleton class from a Nonsingleton class 
(Screen from TurtleScreen). The current implementations of the Screen 
'Singleton' both use the Borg idiom.  Just for *explaining* the 
difference between the two versions of class Screen here concisely,  
I'll use a 'standard' Singleton pattern (roughly equivalent to the Borg 
idiom):

class Spam(object):
   def __init__(self, s):
       self.s = s

class SingleSpam(Spam):
   _inst = None
   def __new__(cls, *args, **kwargs):       
       if cls != type(cls._inst):
           cls._inst = Spam.__new__(cls, *args, **kwargs)
       return cls._inst
   def __init__(self, s):
       if vars(self): return    ######  should this be here???
       Spam.__init__(self, s)

Shortly, this means that SingleSpam.__init__() acts like an empty method 
whenever a (the!) SingleSpam object already exists. 3.0 version of 
Screen acts like this. By contrast 2.6 version of Screen acts as if the 
butlast line were not there and thus reinitializes the Screen object.

3. How to solve it?

Main question: which *behaviour* of the Screen class should be 
preferred.  If  3.0, is it feasible and correct not to call the 
constructor of the parent class if the object already exists?

Additional question: Do you consider the Borg idiom a good solution for 
this task or should the standard singleton pattern as shown above be 
preferred. Or would you suggest a solution/an approach different from both?

Thanks for your patience, and - in advance - for your assistance

Regard,
Gregor




_______________________________________________
Python-Dev mailing list
Python-Dev at python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: http://mail.python.org/mailman/options/python-dev/gregor.lingl%40aon.at



-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: turtle_patch_rc2-diff.txt
URL: <http://mail.python.org/pipermail/python-dev/attachments/20080922/ac8279f3/attachment.txt>


More information about the Python-Dev mailing list