[Python-Dev] turtle.Screen- how to implement best a Singleton

Gregor Lingl gregor.lingl at aon.at
Mon Aug 18 14:14:33 CEST 2008


Thanks for the feedback,
Gregor

Vern Ceder schrieb:
> 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
>
> Gregor Lingl wrote:
>> 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
>>
>>
>>
>>
>



More information about the Python-Dev mailing list