Difference in Python and Ruby interactive shells

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • dmh2000

    Difference in Python and Ruby interactive shells

    I am experimenting with the interactive interpreter environments of
    Python and Ruby and I ran into what seems to be a fundamental
    difference. However I may be doing something wrong in Python. Please
    comment and correct me if I am wrong

    In both languages, you can start up the interactive interpreter
    ('python' and 'irb'), load source files and do stuff, like create
    objects and call their methods. When you want to change something, you
    can edit those same source files outside the environment and reload
    them from within the interactive environment. But, here is the
    difference: with Python, when you reload the source file (module in
    Python terms), it seems that your existing variables stay bound to the
    implementations from the old version of the module. In Ruby, after a
    reload, your existing variables point to the new implementation. At
    least, that is what happens with classes and their methods. This means
    that in Python, if you have an application built up interactively, with
    references to objects, data structures pointing to objects, etc., you
    would have to reconstruct that application to get the new
    implementation. With Ruby, when you load the new implementation, you
    get it immediately.

    here is a simple example:

    -------------------------------------------------------------------------------
    Python interactive shell (python.exe)

    C:\home\dh0072\ rq>python
    Python 2.4.2 (#67, Sep 28 2005, 12:41:11) [MSC v.1310 32 bit (Intel)]
    on win32
    Type "help", "copyright" , "credits" or "license" for more information.

    # load a local file b.py for test
    [color=blue][color=green][color=darkred]
    >>> import b[/color][/color][/color]

    # instantiate an object and call a method
    [color=blue][color=green][color=darkred]
    >>> x = b.B()
    >>> x.p()[/color][/color][/color]
    B

    # edit b.py offline to change method 'p' to do something different then
    reload
    [color=blue][color=green][color=darkred]
    >>> reload(b)[/color][/color][/color]
    [color=blue][color=green][color=darkred]
    >>> x.p()[/color][/color][/color]
    B

    # binding of variable 'x' IS NOT changed. points to old version
    [color=blue][color=green][color=darkred]
    >>> y = b.B()
    >>> y.p()[/color][/color][/color]
    BBBBB

    # new instance of 'b' points to new version
    [color=blue][color=green][color=darkred]
    >>>[/color][/color][/color]
    -------------------------------------------------------------------------------
    Ruby interactive shell (irb.exe)

    C:\home\dh0072\ rq>irb

    # load a local file b.py for test

    irb(main):001:0 > load "b.rb"
    => true

    # instantiate an object and call a method

    irb(main):002:0 > x = B.new
    => #
    irb(main):003:0 > x.p
    B
    => nil

    # edit b.py offline to change method 'p' to do something different then
    reload

    irb(main):004:0 > load "b.rb"
    => true
    irb(main):005:0 > x.p
    BBBB
    => nil

    # binding of variable 'x' IS changed. points to new version

    irb(main):006:0 > y = B.new
    => #
    irb(main):007:0 > y.p
    BBBB
    => nil

    # new instance of 'b' points to new version

  • Claudio Grondi

    #2
    Re: Difference in Python and Ruby interactive shells

    dmh2000 wrote:[color=blue]
    > I am experimenting with the interactive interpreter environments of
    > Python and Ruby and I ran into what seems to be a fundamental
    > difference. However I may be doing something wrong in Python. Please
    > comment and correct me if I am wrong
    >
    > In both languages, you can start up the interactive interpreter
    > ('python' and 'irb'), load source files and do stuff, like create
    > objects and call their methods. When you want to change something, you
    > can edit those same source files outside the environment and reload
    > them from within the interactive environment. But, here is the
    > difference: with Python, when you reload the source file (module in
    > Python terms), it seems that your existing variables stay bound to the
    > implementations from the old version of the module. In Ruby, after a
    > reload, your existing variables point to the new implementation. At
    > least, that is what happens with classes and their methods. This means
    > that in Python, if you have an application built up interactively, with
    > references to objects, data structures pointing to objects, etc., you
    > would have to reconstruct that application to get the new
    > implementation. With Ruby, when you load the new implementation, you
    > get it immediately.[/color]
    I am not fully sure it is what you are speaking about, but I mean, that
    you have overlooked, that in the IDLE menu item [Shell] you have the
    option to restart the shell what takes you back to the initial state.
    It would be interesting to know for me here, if there is in Ruby the
    option to keep the old values when starting a new run?

    Claudio[color=blue]
    >
    > here is a simple example:
    >
    > -------------------------------------------------------------------------------
    > Python interactive shell (python.exe)
    >
    > C:\home\dh0072\ rq>python
    > Python 2.4.2 (#67, Sep 28 2005, 12:41:11) [MSC v.1310 32 bit (Intel)]
    > on win32
    > Type "help", "copyright" , "credits" or "license" for more information.
    >
    > # load a local file b.py for test
    >
    >[color=green][color=darkred]
    >>>>import b[/color][/color]
    >
    >
    > # instantiate an object and call a method
    >
    >[color=green][color=darkred]
    >>>>x = b.B()
    >>>>x.p()[/color][/color]
    >
    > B
    >
    > # edit b.py offline to change method 'p' to do something different then
    > reload
    >
    >[color=green][color=darkred]
    >>>>reload(b)[/color][/color]
    >
    >[color=green][color=darkred]
    >>>>x.p()[/color][/color]
    >
    > B
    >
    > # binding of variable 'x' IS NOT changed. points to old version
    >
    >[color=green][color=darkred]
    >>>>y = b.B()
    >>>>y.p()[/color][/color]
    >
    > BBBBB
    >
    > # new instance of 'b' points to new version
    >
    >
    > -------------------------------------------------------------------------------
    > Ruby interactive shell (irb.exe)
    >
    > C:\home\dh0072\ rq>irb
    >
    > # load a local file b.py for test
    >
    > irb(main):001:0 > load "b.rb"
    > => true
    >
    > # instantiate an object and call a method
    >
    > irb(main):002:0 > x = B.new
    > => #
    > irb(main):003:0 > x.p
    > B
    > => nil
    >
    > # edit b.py offline to change method 'p' to do something different then
    > reload
    >
    > irb(main):004:0 > load "b.rb"
    > => true
    > irb(main):005:0 > x.p
    > BBBB
    > => nil
    >
    > # binding of variable 'x' IS changed. points to new version
    >
    > irb(main):006:0 > y = B.new
    > => #
    > irb(main):007:0 > y.p
    > BBBB
    > => nil
    >
    > # new instance of 'b' points to new version
    >[/color]

    Comment

    • Sybren Stuvel

      #3
      Re: Difference in Python and Ruby interactive shells

      dmh2000 enlightened us with:[color=blue]
      > When you want to change something, you can edit those same source
      > files outside the environment and reload them from within the
      > interactive environment. But, here is the difference: with Python,
      > when you reload the source file (module in Python terms), it seems
      > that your existing variables stay bound to the implementations from
      > the old version of the module.[/color]

      IMO this is the only proper way of doing things. A variable points to
      something in memory. When a module is reloaded, that thing in memory
      is still there - because it is referenced, it does not get garbage
      collected.
      [color=blue]
      > Ruby interactive shell (irb.exe)
      >
      > C:\home\dh0072\ rq>irb
      >
      > # load a local file b.py for test
      >
      > irb(main):001:0 > load "b.rb"
      >=> true
      >
      > # instantiate an object and call a method
      >
      > irb(main):002:0 > x = B.new
      >=> #
      > irb(main):003:0 > x.p
      > B
      >=> nil
      >
      > # edit b.py offline to change method 'p' to do something different then
      > reload
      >
      > irb(main):004:0 > load "b.rb"
      >=> true
      > irb(main):005:0 > x.p
      > BBBB
      >=> nil
      >
      > # binding of variable 'x' IS changed. points to new version[/color]

      IMHO this is nasty. An assignment has already been performed.
      Reloading some module should not (again, IMHO) change anything that
      happened before it was reloaded.

      Sybren
      --
      The problem with the world is stupidity. Not saying there should be a
      capital punishment for stupidity, but why don't we just take the
      safety labels off of everything and let the problem solve itself?
      Frank Zappa

      Comment

      • Diez B. Roggisch

        #4
        Re: Difference in Python and Ruby interactive shells

        > In both languages, you can start up the interactive interpreter[color=blue]
        > ('python' and 'irb'), load source files and do stuff, like create
        > objects and call their methods. When you want to change something, you
        > can edit those same source files outside the environment and reload
        > them from within the interactive environment. But, here is the
        > difference: with Python, when you reload the source file (module in
        > Python terms), it seems that your existing variables stay bound to the
        > implementations from the old version of the module. In Ruby, after a
        > reload, your existing variables point to the new implementation. At
        > least, that is what happens with classes and their methods. This means
        > that in Python, if you have an application built up interactively, with
        > references to objects, data structures pointing to objects, etc., you
        > would have to reconstruct that application to get the new
        > implementation. With Ruby, when you load the new implementation, you
        > get it immediately.[/color]

        I don't know ruby enough to comment on _how_ they achieve that. But I know
        python enough to tell you that your observation is correct, and perfectly
        consistent with what python ususally does.

        The problem here stems from the fact that in python, there are names and
        values. The latter (also referred to as objects) can be bound to a name.

        Now loading a module creates class-objects, and binds them under a name -
        the class-name. But this name is by no means special. You can e.g. do

        class Foo:
        pass

        Foo = 10

        That will create a class that is bound to the name Foo - and the rebind that
        very name to something completely different(tm).

        Now creating an instance of that class creates an object, that has a
        _reference_ to its class - not its name!

        Which means that there is no connection to the _name_ of that class! Well,
        one can get to that, because the class knows the name it was bound to when
        it was created - but that is only for documentary purposes.

        When reloading a module, a new class object is created. And bound to the
        name same name as before - but all instances created before keep a
        reference to their old class. Which makes perfect sense: in python, it is
        possible to create classes individually for each instance, if one wants to
        - by metaclasses, or factoryfunction s like this:

        def createClass():
        class Foo:
        pass
        return Foo

        So - if that works, there is no way how one can know that this reloading of
        a module is anything special.

        Regards,

        Diez

        Comment

        • Steve Juranich

          #5
          Re: Difference in Python and Ruby interactive shells

          dmh2000 wrote:
          [color=blue]
          > I am experimenting with the interactive interpreter environments of
          > Python and Ruby and I ran into what seems to be a fundamental
          > difference. However I may be doing something wrong in Python. Please
          > comment and correct me if I am wrong
          >
          > In both languages, you can start up the interactive interpreter
          > ('python' and 'irb'), load source files and do stuff, like create
          > objects and call their methods. When you want to change something, you
          > can edit those same source files outside the environment and reload
          > them from within the interactive environment. But, here is the
          > difference: with Python, when you reload the source file (module in
          > Python terms), it seems that your existing variables stay bound to the
          > implementations from the old version of the module. In Ruby, after a
          > reload, your existing variables point to the new implementation. At
          > least, that is what happens with classes and their methods. This means
          > that in Python, if you have an application built up interactively, with
          > references to objects, data structures pointing to objects, etc., you
          > would have to reconstruct that application to get the new
          > implementation. With Ruby, when you load the new implementation, you
          > get it immediately.[/color]

          This is correct. I'm a bit fuzzy on the details, so some of this might be
          wrong, but here's what's going on (I'm pretty sure):

          When Python loads (or reloads) a module, it encounters a `class' block,
          which causes it to create a new type in memory. The instances created from
          this type are bound to the type object. This means that after a reload,
          your "B" class is pointing to a different object in memory. However, all
          of your previous instances are still bound to the old definition (which is
          still in memory, it's just not bound to the "B" name any more). As a
          simple test, do 'x.__class__ is y.__class__'. This should return False.

          Ruby, on the other hand, allows you to redefine classes on the fly. So when
          Ruby reads a 'class' block, it's either (1) redefining a previously defined
          object's definition, or (2) creating a new class with the definition in the
          block.

          I *think* that the reason for this is that the Python virtual machine (aka,
          the interpreter) is much more efficient than the Ruby VM. So if you want
          fast code, I'd stick with Python. However, if you regularly build large
          applications in memory from an interactive interpreter, then perhaps Ruby
          is the way for you to go. :-)

          Cheers.
          --
          Steve Juranich
          Tucson, AZ
          USA

          Comment

          • Michele Simionato

            #6
            Re: Difference in Python and Ruby interactive shells

            You want this recipe from Michael Hudson:



            "automatica lly upgrade class instances on reload()"

            Comment

            • malv

              #7
              Re: Difference in Python and Ruby interactive shells

              I think reload should be preceded by import.
              Example:
              Online code modification: upon modifying and saving mytest.py issue on
              the interactive shell:[color=blue][color=green][color=darkred]
              >>>import mytest
              >>>reload(mytes t)[/color][/color][/color]

              The shell should respond with "<module 'mytest' from
              '/root/mytest.py'>" (NOT:mytest.pyc )

              Note that modules importing mytest should not use 'import * from
              mytest' but 'import mytest';
              This requires qualifying all objects as mytest.obj

              Comment

              • Alex Martelli

                #8
                Re: Difference in Python and Ruby interactive shells

                Michele Simionato <michele.simion ato@gmail.com> wrote:
                [color=blue]
                > You want this recipe from Michael Hudson:
                >
                > http://aspn.activestate.com/ASPN/Coo.../Recipe/160164
                >
                > "automatica lly upgrade class instances on reload()"[/color]

                Note that the version in the printed Cookbook (2nd edition) was
                substantially enhanced (mostly by me and Michael working together), I
                don't know if Michael updated his ASPN recipe to reflect that but at any
                rate you can download all the code from the printed Cookbook as a
                zipfile from O'Reilly's site (sorry, I don't recall the URL).


                Alex

                Comment

                • Lou Pecora

                  #9
                  Re: Difference in Python and Ruby interactive shells

                  In article <1144164876.820 737.229810@i40g 2000cwc.googleg roups.com>,
                  "Michele Simionato" <michele.simion ato@gmail.com> wrote:
                  [color=blue]
                  > You want this recipe from Michael Hudson:
                  >
                  > http://aspn.activestate.com/ASPN/Coo.../Recipe/160164
                  >
                  > "automatica lly upgrade class instances on reload()"[/color]


                  Impressive, but YIKES, there ought to be a simpler way to do this. I
                  think during the development phase editing and reloading would be very
                  common and you'd want everything updated. So why is it done the other
                  way, the reference stays the same? Is that useful? Maybe time for a
                  'switch' to set in Python to choose which behavior you want.

                  -- Lou Pecora (my views are my own) REMOVE THIS to email me.

                  Comment

                  • Sybren Stuvel

                    #10
                    Re: Difference in Python and Ruby interactive shells

                    Lou Pecora enlightened us with:[color=blue]
                    > Impressive, but YIKES, there ought to be a simpler way to do this.
                    > I think during the development phase editing and reloading would be
                    > very common and you'd want everything updated.[/color]

                    I hardly ever reload stuff manually during development. I write a
                    script, and execute it. The few times I use reload() it's no big deal
                    to do x = B().
                    [color=blue]
                    > So why is it done the other way, the reference stays the same? Is
                    > that useful?[/color]

                    It's predictable. Variables point to one and the same thing, unless
                    you manipulate them directly.
                    [color=blue]
                    > Maybe time for a 'switch' to set in Python to choose which behavior
                    > you want.[/color]

                    That wouldn't be pythonic. People would start using that switch in
                    their programs too, causing a single command to act differently in
                    each program.

                    Sybren
                    --
                    The problem with the world is stupidity. Not saying there should be a
                    capital punishment for stupidity, but why don't we just take the
                    safety labels off of everything and let the problem solve itself?
                    Frank Zappa

                    Comment

                    • dmh2000

                      #11
                      Re: Difference in Python and Ruby interactive shells

                      Thanks all for the responses. Extra kudos to Steve J and Michele S.
                      that cleared it up for me.

                      the context of my question comes from reading up on Lisp in "Loving
                      Lisp - the Savy Programmer's Secret Weapon",
                      http://www.markwatson.com/opencontent/lisp_lic.htm, where the author
                      described building up a large system during test, that took a long to
                      to load. He was showing one reason why a dynamic language was more
                      productive than a statically compiled language.

                      Comment

                      • Peter Otten

                        #12
                        Re: Difference in Python and Ruby interactive shells

                        Alex Martelli wrote:
                        [color=blue]
                        > Michele Simionato <michele.simion ato@gmail.com> wrote:
                        >[color=green]
                        >> You want this recipe from Michael Hudson:
                        >>
                        >> http://aspn.activestate.com/ASPN/Coo.../Recipe/160164
                        >>
                        >> "automatica lly upgrade class instances on reload()"[/color]
                        >
                        > Note that the version in the printed Cookbook (2nd edition) was
                        > substantially enhanced (mostly by me and Michael working together), I
                        > don't know if Michael updated his ASPN recipe to reflect that but at any
                        > rate you can download all the code from the printed Cookbook as a
                        > zipfile from O'Reilly's site (sorry, I don't recall the URL).[/color]



                        The files are named cb2_6_21_*.py, but the book has the recipe in chapter
                        20.15.

                        Peter

                        Comment

                        • Alex Martelli

                          #13
                          Re: Difference in Python and Ruby interactive shells

                          Peter Otten <__peter__@web. de> wrote:
                          [color=blue]
                          > Alex Martelli wrote:
                          >[color=green]
                          > > Michele Simionato <michele.simion ato@gmail.com> wrote:
                          > >[color=darkred]
                          > >> You want this recipe from Michael Hudson:
                          > >>
                          > >> http://aspn.activestate.com/ASPN/Coo.../Recipe/160164
                          > >>
                          > >> "automatica lly upgrade class instances on reload()"[/color]
                          > >
                          > > Note that the version in the printed Cookbook (2nd edition) was
                          > > substantially enhanced (mostly by me and Michael working together), I
                          > > don't know if Michael updated his ASPN recipe to reflect that but at any
                          > > rate you can download all the code from the printed Cookbook as a
                          > > zipfile from O'Reilly's site (sorry, I don't recall the URL).[/color]
                          >
                          > http://examples.oreilly.com/pythonco...2_examples.zip
                          >
                          > The files are named cb2_6_21_*.py, but the book has the recipe in chapter
                          > 20.15.[/color]

                          Ah, yes, good point: there's an "off by one" numbering issue there, due
                          to the fact that the O'Reilly Safari online verbatim version of the book
                          numbers the preface as "1" while the printed version doesn't, so chapter
                          1 in the printed version is 2.something on Safari, etc.


                          Alex

                          Comment

                          • Nick Craig-Wood

                            #14
                            Re: Difference in Python and Ruby interactive shells

                            Lou Pecora <pecoraREMOVE@T HISanvil.nrl.na vy.mil> wrote:[color=blue]
                            > Impressive, but YIKES, there ought to be a simpler way to do this. I
                            > think during the development phase editing and reloading would be very
                            > common and you'd want everything updated.[/color]

                            Sorry I missed this thread...

                            This is what I use which is easy and works just fine. I only type it
                            once and then press up arrow to get it back!

                            import workinprogress; reload(workinpr ogress); del(workinprogr ess); from workinprogress import *

                            That gives you the module and all its globals rebound.

                            --
                            Nick Craig-Wood <nick@craig-wood.com> -- http://www.craig-wood.com/nick

                            Comment

                            Working...