Global Variables in OOP and Python

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

    #1

    Global Variables in OOP and Python

    Hello,

    I have questions about global variables in OOP (in general) and Python
    (in specific). I understand (I think) that global variables are
    generally not a good idea. However, if there are variables that need to
    be accessed by a number of classes that exists in separate namespaces
    (files), what would be the best way to do this?

    So far, I have approached the problem by making the variables
    attributes of one class and passing instances of the class as variables
    to the other class' methods.

    The other way I thought of is to create a separate class that consists
    of the variables and to use the

    from <file name> import *

    in all of the files (namespaces) where it is needed.

    Is there a better way?

    Are the two ideas presented above acceptable? If so, is one better than
    the other from an OOP POV?

  • Steven D'Aprano

    #2
    Re: Global Variables in OOP and Python

    On Fri, 30 Dec 2005 15:03:54 -0800, newbie wrote:
    [color=blue]
    > Hello,
    >
    > I have questions about global variables in OOP (in general) and Python
    > (in specific). I understand (I think) that global variables are
    > generally not a good idea. However, if there are variables that need to
    > be accessed by a number of classes that exists in separate namespaces
    > (files), what would be the best way to do this?
    >
    > So far, I have approached the problem by making the variables
    > attributes of one class and passing instances of the class as variables
    > to the other class' methods.[/color]


    Do you mean something like this?

    # Module care_and_feedin g

    import birds
    import foods

    def feed_my_pet():
    pet = birds.Parrot("N orwegian Blue")
    snack = foods.Spam("A tasty meat-like treat")
    pet.eats(snack)
    return "Yummy!"


    That is a good way of handling the problem.


    [color=blue]
    > The other way I thought of is to create a separate class that consists
    > of the variables and to use the
    >
    > from <file name> import *
    >
    > in all of the files (namespaces) where it is needed.[/color]

    That's a bad way of handling it. It has all the worst aspects of using
    global variables, plus the worst aspects of import * (namespace pollution
    and shadowing of existing names).

    Unless I'm badly mistaken, Guido has decided that "from module import *"
    was a mistake, and that will be removed from the (legendary) Python 3, if
    and when it gets created. In the meantime, it is highly recommended that
    you don't use that form.

    [color=blue]
    > Is there a better way?
    >
    > Are the two ideas presented above acceptable? If so, is one better than
    > the other from an OOP POV?[/color]


    I think the first way is fine, but of course the Devil is in the details:
    I can't judge your code without seeing it.


    --
    Steven.

    Comment

    • Mike Meyer

      #3
      Re: Global Variables in OOP and Python

      "newbie" <solaris_1234@y ahoo.com> writes:[color=blue]
      > So far, I have approached the problem by making the variables
      > attributes of one class and passing instances of the class as variables
      > to the other class' methods.[/color]

      That's the standard way to do it in OO languages.
      [color=blue]
      > The other way I thought of is to create a separate class that consists
      > of the variables and to use the
      >
      > from <file name> import *
      >
      > in all of the files (namespaces) where it is needed.[/color]

      Except for one detail, this is a Pythonesque method. The detail is
      that "from <module> import *" is generally considered a bad
      idea. There are two reasons for this:

      1) Blindly adding everything in a module to your namespace is liable
      to cause collisions. If the module you're doing this to is stable,
      this isn't much of a problem.

      2) It makes finding where a variable came from harder. Having to
      search extra modules for globals is a pain. If the exported names have
      a prefix on them to identify the module, that goes away. But in that
      case, you might as well do "import <module> as <prefix>", and leave
      the prefix off the variable names in the module.

      A better way to do this is to give your module a name that denotes
      it's function ("config", for instances, or maybe even "globals") and
      use that.
      [color=blue]
      > Are the two ideas presented above acceptable? If so, is one better than
      > the other from an OOP POV?[/color]

      With the one change, they are. From an OO point of view, they're
      almost identical. In Python, a module is an object, so the difference
      is whether you want to instantiate a custom class to hold your
      globals, or use the builtin module type for that purpose.

      <mike

      --
      Mike Meyer <mwm@mired.or g> http://www.mired.org/home/mwm/
      Independent WWW/Perforce/FreeBSD/Unix consultant, email for more information.

      Comment

      • Gary Herron

        #4
        Re: Global Variables in OOP and Python

        newbie wrote:
        [color=blue]
        >Hello,
        >
        >I have questions about global variables in OOP (in general) and Python
        >(in specific). I understand (I think) that global variables are
        >generally not a good idea. However, if there are variables that need to
        >be accessed by a number of classes that exists in separate namespaces
        >(files), what would be the best way to do this?
        >
        >So far, I have approached the problem by making the variables
        >attributes of one class and passing instances of the class as variables
        >to the other class' methods.
        >
        >The other way I thought of is to create a separate class that consists
        >of the variables and to use the
        >
        >from <file name> import *
        >
        >[/color]
        That form is deprecated. Better (and certainly clearer to any reader of
        the code) is to leave them in the module.

        Define a module, say Parameters, that defines any number of variables
        containing useful values. Then
        import Parameters
        wherever you want and refer to
        Parameters.a
        and
        Parameters.b

        You can even add runtime parameters (say options and paths from the
        command line) to the module during your initialization code, and those
        will be available wherever Parameters is imported:
        Parameters.xyzz y = 'whatever'
        Parameters.star tDirectory = os.getcwd() # Get working directory at startup
        (Even if the import of Parameters in some file occurs before the
        initialization code has a chance to run.)

        Gary Herron
        [color=blue]
        >in all of the files (namespaces) where it is needed.
        >
        >Is there a better way?
        >
        >Are the two ideas presented above acceptable? If so, is one better than
        >the other from an OOP POV?
        >
        >
        >[/color]

        Comment

        • Brian van den Broek

          #5
          Re: Global Variables in OOP and Python

          Gary Herron said unto the world upon 30/12/05 08:03 PM:[color=blue]
          > newbie wrote:
          >
          >[color=green]
          >>Hello,
          >>
          >>I have questions about global variables in OOP (in general) and Python
          >>(in specific). I understand (I think) that global variables are
          >>generally not a good idea. However, if there are variables that need to
          >>be accessed by a number of classes that exists in separate namespaces
          >>(files), what would be the best way to do this?
          >>
          >>So far, I have approached the problem by making the variables
          >>attributes of one class and passing instances of the class as variables
          >>to the other class' methods.
          >>
          >>The other way I thought of is to create a separate class that consists
          >>of the variables and to use the
          >>[/color]
          >[color=green]
          >>from <file name> import *[/color]
          >[color=green]
          >>
          >>[/color]
          >
          > That form is deprecated. Better (and certainly clearer to any reader of
          > the code) is to leave them in the module.
          >
          > Define a module, say Parameters, that defines any number of variables
          > containing useful values. Then
          > import Parameters
          > wherever you want and refer to
          > Parameters.a
          > and
          > Parameters.b[/color]

          <snip>

          An other variant seems rarely to come up.

          import Parameters as P

          provides almost all the brevity of the * variant and none of the dangers.

          Best to all,

          Brian vdB

          Comment

          • Steven D'Aprano

            #6
            Re: Global Variables in OOP and Python

            On Fri, 30 Dec 2005 20:00:51 -0500, Mike Meyer wrote:

            [color=blue][color=green]
            >> The other way I thought of is to create a separate class that consists
            >> of the variables and to use the
            >>
            >> from <file name> import *
            >>
            >> in all of the files (namespaces) where it is needed.[/color]
            >
            > Except for one detail, this is a Pythonesque method. The detail is
            > that "from <module> import *" is generally considered a bad
            > idea. There are two reasons for this:[/color]

            Agree about from module import * being bad, but it is still generally poor
            practice for the same reason using global variables is generally poor
            practice.

            [color=blue]
            > 1) Blindly adding everything in a module to your namespace is liable
            > to cause collisions. If the module you're doing this to is stable,
            > this isn't much of a problem.[/color]

            How does stability come in to it? If I have a module spam with an object
            parrot, and it imports another module with an object parrot, there will be
            a namespace collision regardless of whether the two modules are 0.1 alpha
            versions or 3.2 stable versions. If the collision is subtle enough, the
            bug might take years to discover.

            If you mean that namespace collisions are less likely to have remained
            undetected by the time the modules reach stability, then I will cautiously
            agree with you. But if you mean what you say, that collisions are not a
            problem for stable modules, then I disagree strongly.


            [color=blue]
            > 2) It makes finding where a variable came from harder. Having to
            > search extra modules for globals is a pain. If the exported names have
            > a prefix on them to identify the module, that goes away. But in that
            > case, you might as well do "import <module> as <prefix>", and leave
            > the prefix off the variable names in the module.[/color]

            Agreed.

            [color=blue]
            > A better way to do this is to give your module a name that denotes
            > it's function ("config", for instances, or maybe even "globals") and
            > use that.[/color]

            And an even better way is to use the absolute minimum number of global
            variables possible. In general, that means global functions and classes
            Good, global instances and other data Bad.

            In other words, any time you feel the need to put "global name" in a
            function or method, think twice, have a cold shower, do fifty push-ups,
            and then re-write the function to not use globals. 99 times out of a 100,
            you'll end up with better code.


            --
            Steven.

            Comment

            • Steven D'Aprano

              #7
              Re: Global Variables in OOP and Python

              On Sat, 31 Dec 2005 21:21:29 +0000, Dennis Lee Bieber wrote:
              [color=blue]
              > On Sat, 31 Dec 2005 11:37:38 +1100, Steven D'Aprano
              > <steve@REMOVETH IScyber.com.au> declaimed the following in
              > comp.lang.pytho n:
              >[color=green]
              >>
              >> Do you mean something like this?
              >>
              >> # Module care_and_feedin g
              >>
              >> import birds
              >> import foods
              >>
              >> def feed_my_pet():
              >> pet = birds.Parrot("N orwegian Blue")
              >> snack = foods.Spam("A tasty meat-like treat")
              >> pet.eats(snack)
              >> return "Yummy!"
              >>
              >>
              >> That is a good way of handling the problem.
              >>[/color]
              > Except for the minor facet that you are buying a new parrot each
              > time, and the bird dies after going "Yummy!" <G>[/color]

              It's a Norwegian Blue with beautiful plumage. It's not dead, it's just
              pining for the fjords.



              --
              Steven.

              Comment

              • Kay Schluehr

                #8
                Re: Global Variables in OOP and Python


                Steven D'Aprano wrote:[color=blue]
                > On Fri, 30 Dec 2005 20:00:51 -0500, Mike Meyer wrote:
                >
                >[color=green][color=darkred]
                > >> The other way I thought of is to create a separate class that consists
                > >> of the variables and to use the
                > >>
                > >> from <file name> import *
                > >>
                > >> in all of the files (namespaces) where it is needed.[/color]
                > >
                > > Except for one detail, this is a Pythonesque method. The detail is
                > > that "from <module> import *" is generally considered a bad
                > > idea. There are two reasons for this:[/color]
                >
                > Agree about from module import * being bad, but it is still generally poor
                > practice for the same reason using global variables is generally poor
                > practice.[/color]

                No, I don't think so. The general wisdom is that global variables are
                bad not because they are global, but because they are variable.
                Responsibility about state mutation is scattered across the code and
                spaghetti is the likely consequence. This cannot be prevented by
                changing the access protocoll ( getters / setters ) or using static
                variables. Mutable OO-singletons are not less harmfull than good old
                globals.

                Namespace pollution or name clashes are another issue and we have to
                make a tradeoff between easeness of following references and namespace
                security on the one hand conciseness on the other. I'm not completely
                unhappy using "True" instead of "__builtins__.T rue" allthough the
                latter would be more pure.

                Comment

                • Steven D'Aprano

                  #9
                  Re: Global Variables in OOP and Python

                  On Sun, 01 Jan 2006 06:48:48 -0800, Kay Schluehr wrote:
                  [color=blue][color=green]
                  >> Agree about from module import * being bad, but it is still generally poor
                  >> practice for the same reason using global variables is generally poor
                  >> practice.[/color]
                  >
                  > No, I don't think so. The general wisdom is that global variables are
                  > bad not because they are global, but because they are variable.
                  > Responsibility about state mutation is scattered across the code and
                  > spaghetti is the likely consequence. This cannot be prevented by
                  > changing the access protocoll ( getters / setters ) or using static
                  > variables. Mutable OO-singletons are not less harmfull than good old
                  > globals.[/color]

                  Now that you mention it, how obvious it is. That is good thinking,
                  thanks.



                  --
                  Steven.

                  Comment

                  Working...