I thought I'd 'got' globals but...

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

    #1

    I thought I'd 'got' globals but...

    I thought I had 'got' globals but this one seems strange.
    I want my example function 'doIt' to use and optionally modify a module
    variable 'gname', so I declare 'global gname' in the function, but when
    modified it doesn't stay modified.

    gname = 'Sue'
    def doIt(name = gname):
    global gname
    gname = name
    print 'doIt name', name, 'gname', gname

    print 'start gname', gname
    doIt()
    doIt(name='Lisa ')
    doIt()
    print 'finish gname', gname

    gives...
    start gname Sue
    doIt name Sue gname Sue
    doIt name Lisa gname Lisa
    doIt name Sue gname Sue
    finish gname Sue

    The variable gname has reverted back to value 'Sue'

    Curiously though, without the third doIt() call, it works...
    print 'start gname', gname
    doIt()
    doIt(name='Lisa ')
    #doIt()
    print 'finish gname', gname

    gives...
    start gname Sue
    doIt name Sue gname Sue
    doIt name Lisa gname Lisa
    finish gname Lisa

    The variable gname has been modified to 'Lisa'

    Any ideas how I can make the 'Lisa' assignment permanent forever in 2nd
    doIt? Thanks

    (Note. Contrived example substitutes for a web-type app, where, if the
    page is called without arguments then it displays the global defaults.
    If the page is called with form arguments then it should be able to
    change the global defaults)

  • Bruno Desthuilliers

    #2
    Re: I thought I'd 'got' globals but...

    meridian wrote:
    I thought I had 'got' globals but this one seems strange.
    I want my example function 'doIt' to use and optionally modify a module
    variable 'gname', so I declare 'global gname' in the function, but when
    modified it doesn't stay modified.
    >
    gname = 'Sue'
    def doIt(name = gname):
    This is a FAQ, cf:
    Contents: General Python FAQ- General Information- What is Python?, What is the Python Software Foundation?, Are there copyright restrictions on the use of Python?, Why was Python created in the fi...


    Briefly : default args are eval'd only once at load/import time.

    Any ideas how I can make the 'Lisa' assignment permanent forever in 2nd
    doIt? Thanks
    def doIt(name=None) :
    global gname
    if name is None:
    name = gname
    else:
    gname = name
    (Note. Contrived example substitutes for a web-type app, where, if the
    page is called without arguments then it displays the global defaults.
    If the page is called with form arguments then it should be able to
    change the global defaults)
    Modifying globals from within a function is usually a very bad idea.


    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in 'onurb@xiludom. gro'.split('@')])"

    Comment

    • meridian

      #3
      Re: I thought I'd 'got' globals but...


      Bruno Desthuilliers wrote:
      def doIt(name=None) :
      global gname
      if name is None:
      name = gname
      else:
      gname = name
      >
      Thanks Bruno, works a treat...

      Comment

      • Bruno Desthuilliers

        #4
        Re: I thought I'd 'got' globals but...

        meridian wrote:
        Bruno Desthuilliers wrote:
        >
        >>def doIt(name=None) :
        > global gname
        > if name is None:
        > name = gname
        > else:
        > gname = name
        >>
        >
        >
        Thanks Bruno, works a treat...
        >
        But still very probably a bad idea.

        --
        bruno desthuilliers
        python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
        p in 'onurb@xiludom. gro'.split('@')])"

        Comment

        • meridian

          #5
          Re: I thought I'd 'got' globals but...


          Bruno Desthuilliers wrote:
          meridian wrote:
          Bruno Desthuilliers wrote:
          >def doIt(name=None) :
          global gname
          if name is None:
          name = gname
          else:
          gname = name
          >

          Thanks Bruno, works a treat...
          But still very probably a bad idea.
          >
          Ok, my curiosity is pique'd - is there a better way to hold my
          app/module globals?
          I must say I'd prefer not to write global <varin every function, for
          every global var I need.
          Maybe there's a simpler way to structure?... by a global class or
          something?
          Cheers
          Steve

          Comment

          • meridian

            #6
            Re: I thought I'd 'got' globals but...


            You mentioned earlier that
            "Modifying globals from within a function is usually a very bad idea."

            Most of my app consists of functions or class/object functions, that's
            all I do in OOP.
            Did you mean that modifying globals from anywhere is bad? or globals
            are bad? or don't code using methods/functions? not sure...

            Comment

            • Bruno Desthuilliers

              #7
              Re: I thought I'd 'got' globals but...

              meridian a écrit :
              Bruno Desthuilliers wrote:
              >
              >>meridian wrote:
              >>
              >>>Bruno Desthuilliers wrote:
              >>>
              >>>
              >>>>def doIt(name=None) :
              >>>global gname
              >>>if name is None:
              >>> name = gname
              >>>else:
              >>> gname = name
              >>>>
              >>>
              >>>
              >>>Thanks Bruno, works a treat...
              >>>
              >>
              >>But still very probably a bad idea.
              >>
              >
              Ok, my curiosity is pique'd - is there a better way to hold my
              app/module globals?
              Probably !-)

              Now which one depends on your app design and execution model...
              I must say I'd prefer not to write global <varin every function, for
              every global var I need.
              Maybe there's a simpler way to structure?... by a global class or
              something?
              <ot>What is a "global class" ?</ot>

              The problem with "app globals" is that they introduce too much coupling
              (you end up having all your code depending on the globals). So the first
              thing to do is identify who really needs to know what, and who is
              responsible for knowing what. Anyway, most globals should be
              configuration stuff - so usually read only. There are very good reasons
              to avoid modifying globals in functions, and specially when it comes to
              web programming where you have to handle concurrent access (which is why
              I insist on telling you that what you want to do may be very dangerous).

              Usually one uses a variant of the MVC, which helps separating concerns :
              the model is about data (structure and persistance), the view(s) about
              outputs (display data), and the controler about inputs (processing the
              request). The flow is something like: controller parses request, takes
              any appropriate action, selects appropriate elements from the model,
              feed'em to appropriate view, and returns the result of view execution as
              a response (general scheme, depends on whether it's plain cgi,
              mod_python, fastcgi, wsgi, standalone server or whatnot).

              It's clear that the controler needs some knowldge about the model and
              the views, that the views are tightly coupled to the model but don't
              need to know about the controller, and that the model just don't give a
              damn about both controller and views. So we have:

              controller -depends on model and view
              view -depends on model
              model -depends on nobody

              Since handling a request is the controller's duty, the model should not
              know about the request. The only 'global' things the model has to know
              are related to data access configuration (db connection string, physical
              path to resources on the filesystem etc...). Since the model is called
              by the controller, it's the controller's job to pass these informations
              to the model when appropriate.

              Views may also need to access app-wide settings like urls to resources,
              localisation stuff etc. Here again, since views are invoked by the
              controller, it's usually the controller that is responsible for passing
              relevant knowledge to the views - either directly (raw data) or
              indirectly (thru some helper objects that holds the required knowledge
              and are called by the view code).

              As you can see, you've already eliminated any needs for globals in both
              the views and the model (view or model specific module-level
              pseudo-constants set aside, but then it's mostly safe).

              I don't know which web solution you use, but I strongly suggest that you
              take some time studying existing web applications or frameworks like
              Trac, Django, CherryPy etc.

              HTH

              Comment

              • Bruno Desthuilliers

                #8
                Re: I thought I'd 'got' globals but...

                meridian a écrit :
                You mentioned earlier that
                "Modifying globals from within a function is usually a very bad idea."
                >
                Most of my app consists of functions or class/object functions, that's
                all I do in OOP.
                Did you mean that modifying globals from anywhere is bad?
                Yes, definitively. Even without concurrent access, it very rapidly turns
                the code into an unscrutable mess.
                or globals
                are bad?
                Mostly, yes.

                As usual, this is not a hard rule but a guideline. But I use as few
                globals as possible, and almost all of them are read-only. The very few
                exceptions are dirty hacks, mostly called at init time.
                or don't code using methods/functions?
                Err...

                Comment

                • meridian

                  #9
                  Re: I thought I'd 'got' globals but...

                  Thanks Bruno. Not only do you give solutions to my problem but also
                  throw in great MVC tutorials too.
                  You're a gent.

                  I'm using
                  controller -A CherryPy app
                  views -Cheetah Templating for the html & data
                  model -mostly SQLite DB using pysqlite
                  also Config

                  It's only a desk-web app for single-user, so no concurrency issues.
                  However, taking on board your advice to avoid globals, I've now
                  realised that the info that I need to retain between pages can simply
                  be session information (for the only user) that can be initialised at
                  startup from the config.
                  So I'm looking at just storing it all in the cherrypy.sessio n ram vs
                  using python globals.
                  Thanks again & Regards
                  Steve

                  Comment

                  • Bruno Desthuilliers

                    #10
                    Re: I thought I'd 'got' globals but...

                    meridian wrote:
                    Thanks Bruno. Not only do you give solutions to my problem but also
                    throw in great MVC tutorials too.
                    You're a gent.
                    (blush)
                    I'm using
                    controller -A CherryPy app
                    views -Cheetah Templating for the html & data
                    model -mostly SQLite DB using pysqlite
                    also Config
                    >
                    It's only a desk-web app for single-user, so no concurrency issues.
                    Err... I would not be so confident wrt/ this point. What about having
                    two browser windows opened on different pages of the app ?
                    However, taking on board your advice to avoid globals, I've now
                    realised that the info that I need to retain between pages can simply
                    be session information (for the only user) that can be initialised at
                    startup from the config.
                    So I'm looking at just storing it all in the cherrypy.sessio n ram vs
                    using python globals.
                    Think this will be better !-)

                    But still, avoid overusing sessions - ie, don't make session available
                    to objects just for covenience when you can pass required data as params.

                    My 2 cents...

                    --
                    bruno desthuilliers
                    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
                    p in 'onurb@xiludom. gro'.split('@')])"

                    Comment

                    • Luis M. González

                      #11
                      Re: I thought I'd 'got' globals but...


                      Bruno Desthuilliers wrote:
                      >
                      def doIt(name=None) :
                      global gname
                      if name is None:
                      name = gname
                      else:
                      gname = name
                      >
                      Sorry for this very basic question, but I don't understand why I should
                      add the global into the function body before using it.
                      This function works even if I don't add the global.
                      Just to try this out, I wrote this variant:

                      gname = 'Luis'

                      def doIt2(name=None ):
                      if name is None:
                      name = gname
                      return name

                      print doIt2() --returns Luis.

                      So, what's the point of writing the function this way instead?

                      def doIt2(name=None ):
                      global gname
                      if name is None:
                      name = gname
                      return name


                      luis

                      Comment

                      • nate

                        #12
                        Re: I thought I'd 'got' globals but...

                        try this:

                        gname = 'nate'
                        def test():
                        gname = 'amy'
                        print gname

                        test()
                        print gname

                        outputs:
                        'amy'
                        'nate'

                        whereas this:
                        gname = 'nate'
                        def test():
                        global gname
                        gname = 'amy'
                        print gname

                        test()
                        print gname

                        outputs:
                        'amy'
                        'amy'

                        Luis M. González wrote:
                        Bruno Desthuilliers wrote:

                        def doIt(name=None) :
                        global gname
                        if name is None:
                        name = gname
                        else:
                        gname = name
                        >
                        Sorry for this very basic question, but I don't understand why I should
                        add the global into the function body before using it.
                        This function works even if I don't add the global.
                        Just to try this out, I wrote this variant:
                        >
                        gname = 'Luis'
                        >
                        def doIt2(name=None ):
                        if name is None:
                        name = gname
                        return name
                        >
                        print doIt2() --returns Luis.
                        >
                        So, what's the point of writing the function this way instead?
                        >
                        def doIt2(name=None ):
                        global gname
                        if name is None:
                        name = gname
                        return name


                        luis

                        Comment

                        • Luis M. González

                          #13
                          Re: I thought I'd 'got' globals but...


                          nate wrote:
                          try this:
                          >
                          gname = 'nate'
                          def test():
                          gname = 'amy'
                          print gname
                          >
                          test()
                          print gname
                          >
                          outputs:
                          'amy'
                          'nate'
                          >
                          whereas this:
                          gname = 'nate'
                          def test():
                          global gname
                          gname = 'amy'
                          print gname
                          >
                          test()
                          print gname
                          >
                          outputs:
                          'amy'
                          'amy'
                          OK, so I should include the global only if I plan to modify it.
                          Otherwise, I don't need to include it. Am I right?

                          Comment

                          • nate

                            #14
                            Re: I thought I'd 'got' globals but...

                            OK, so I should include the global only if I plan to modify it.
                            Otherwise, I don't need to include it. Am I right?
                            I guess you could say that's true. I'm hardly an expert so I couldn't
                            say there aren't other potential ramifications. (anyone?)

                            But, as a rule I would declare the global variable always because
                            1) it makes my intention clear
                            2) if I later decided to modify the global variable, I would be less
                            likely to introduce a bug by forgetting to declare it global.

                            Comment

                            • Markus Wankus

                              #15
                              Re: I thought I'd 'got' globals but...

                              On Fri, 07 Jul 2006 19:41:36 -0400, Luis M. González <luismgz@gmail. com>
                              wrote:
                              ..
                              ..
                              OK, so I should include the global only if I plan to modify it.
                              Otherwise, I don't need to include it. Am I right?
                              >
                              Correct. Globals are always available to read from. You need to declare
                              them if you want to modify them in another scope. Like nate, I also tend
                              to declare them all the time if I am going to use them, just for clarity.

                              M.

                              Comment

                              Working...