[Tutor] Python vs. Ruby - and a queston on Tkinter-Canvas

Gregor Lingl glingl at aon.at
Thu Oct 30 15:08:21 EST 2003



Andrei schrieb:

>Danny Yoo wrote on Wed, 29 Oct 2003 16:28:52 -0800 (PST):
>
>  
>
>>>Python docs are a lot better too, especially the ones in the ActiveState
>>>distro; the there isn't even a "docs" entry in my Ruby program group!
>>>Another advantage is that the whole of Python is quite English-oriented,
>>>while a lot of Ruby stuff is still in Japanese only (at least I presume
>>>it's Japanese), or really broken English.
>>>      
>>>
>>Hi Andrei,
>>
>>There are some good Ruby books out there.  In fact, the folks who wrote
>>"The Pragmatic Programmer" have released their own Ruby book online:
>>
>>    http://www.rubycentral.com/book/index.html
>>    
>>
>
>Yep, 
>
...

It was approx. 2 years ago, when I decided  to  use (and promote)  
Python  as a
first learning language in my classes (sharing my experiences with other 
teachers here in
Vienna) and there is not a single reason why I should change to another 
language, be it
Ruby or not, now. Instead many pragmatic considerations lead me to stick 
with
Python for my work.

Nevertheless I'm curious, wether a look at Ruby would be rewarding and 
interesting, just
to know what's going on in the world (of computer languages). So the 
above link led me
to a Ruby-Tk program, which I  tried, just for fun, to translate into 
Python-Tkinter

Ruby-Code:

require 'tk'

class Draw
  def do_press(x, y)
    @start_x = x
    @start_y = y
    @current_line = TkcLine.new(@canvas, x, y, x, y)
  end
  def do_motion(x, y)
    if @current_line
      @current_line.coords @start_x, @start_y, x, y
    end
  end
  def do_release(x, y)
    if @current_line
      @current_line.coords @start_x, @start_y, x, y
      @current_line.fill 'black'
      @current_line = nil
    end
  end
  def initialize(parent)
    @canvas = TkCanvas.new(parent)
    @canvas.pack
    @start_x = @start_y = 0
    @canvas.bind("1", proc{|e| do_press(e.x, e.y)})
    @canvas.bind("2", proc{ puts @canvas.postscript({}) })
    @canvas.bind("ButtonRelease-1",
                 proc{|x, y| do_release (x, y)}, "%x %y")
  end
end

root = TkRoot.new{ title 'Canvas' }
Draw.new(root)
Tk.mainloop


Translation to Python:

import Tkinter as Tk

class Draw:
    def do_press(self,e):
        self.start_x = e.x
        self.start_y = e.y
        self.current_line = self.canvas.create_line(e.x, e.y, e.x, e.y)
    def do_motion(self,e):
        if self.current_line:
            self.canvas.coords(self.current_line,
                               self.start_x, self.start_y, e.x, e.y)
    def do_release(self,e):
        if self.current_line:
            self.canvas.coords(self.current_line,
                               self.start_x, self.start_y, e.x, e.y)
            self.canvas.itemconfig(self.current_line, fill="black")
            self.current_line = None
    def __init__(self, parent):
        self.canvas = Tk.Canvas(parent)
        self.canvas.pack()
        # self.start_x = self.start_y = 0  ## is this necessary in Ruby?
        self.canvas.bind("<1>",self.do_press)
        self.canvas.bind("<B1-Motion>", self.do_motion)
        self.canvas.bind("<ButtonRelease-1>", self.do_release)
       
root = Tk.Tk()
root.title("Canvas")
Draw(root)
root.mainloop()

Indeed very similar. This example can be made even more similar, when 
using the Canvas module:

import Tkinter as Tk
from Canvas import Line

class Draw:
    def do_press(self,e):
        self.start_x = e.x
        self.start_y = e.y
        self.current_line = Line(self.canvas, e.x, e.y, e.x, e.y)
    def do_motion(self,e):
        if self.current_line:
            self.current_line.coords(((self.start_x, self.start_y), 
(e.x, e.y)))
    def do_release(self,e):
        if self.current_line:
            self.current_line.coords(((self.start_x, self.start_y), 
(e.x, e.y)))
            self.current_line.config(fill="black")
            self.current_line = None
    def __init__(self, parent):
        self.canvas = Tk.Canvas(parent)
        self.canvas.pack()
        # self.start_x = self.start_y = 0 ## is this necessary in Ruby?
        self.canvas.bind("<1>",self.do_press)
        self.canvas.bind("<B1-Motion>", self.do_motion)
        self.canvas.bind("<ButtonRelease-1>", self.do_release)
       
root = Tk.Tk()
root.title("Canvas")
Draw(root)
root.mainloop()

Alas! The canvas module is declared deprecated. So we are discouraged using
canvas items as objects, contrary to Ruby-Tk users.

####  So my MAIN QUESTION, which in fact has nothing to do with Ruby:  
#######
Why is the - former "experimental" - Canvas module declared deprecated now?
##################################################################

Only one remark concerning Python and Ruby:
One of the most useful, wonderfully beautiful features of Python is 
(imho) how
functions as first class objects are handled. (One can observe this even 
in the above
"translation". Is the back side of this coin, that Ruby doesn't need 
parentheses for
function calls (at least in some cases)?) So Python enforces to "think 
in function-objects"
and this is very fruitful for showing, teaching and experiencing the 
power of abstraction.   

And even the use of self - an often critisized feature - is from my 
point  of view
more an advantage than a disadvantage in the educational context. As it 
makes
explicit what otherwise nevertheless is the case implicitely.

Regards, Gregor

P.S. (  ;-)   ):   Those who can't bear it, could make another step 
(although only visually)
in direction to Ruby by writing:

import Tkinter as Tk
from Canvas import Line

class Draw:
    def do_press(_,e):
        _.start_x = e.x
        _.start_y = e.y
        _.current_line = Line(_.canvas, e.x, e.y, e.x, e.y)
    def do_motion(_,e):
        if _.current_line:
            _.current_line.coords(((_.start_x, _.start_y), (e.x, e.y)))
    def do_release(_,e):
        if _.current_line:
            _.current_line.coords(((_.start_x, _.start_y), (e.x, e.y)))
            _.current_line.config(fill="black")
            _.current_line = None
    def __init__(_, parent):
        _.canvas = Tk.Canvas(parent)
        _.canvas.pack()
        # _.start_x = _.start_y = 0 ## is this necessary in Ruby?
        _.canvas.bind("<1>",_.do_press)
        _.canvas.bind("<B1-Motion>", _.do_motion)
        _.canvas.bind("<ButtonRelease-1>", _.do_release)
       
root = Tk.Tk()
root.title("Canvas")
Draw(root)
root.mainloop()

:-P

P.P.S.: I hope I expressed my ideas clearly enough, so you can grasp 
what I mean. When content
becomes a bit more complex I feel the limits of my restricted knowledge 
of English. Perhaps I should
use part of my time to enhance my English instead of learning one more 
computer language.




More information about the Tutor mailing list