Python Global Constant

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

    Python Global Constant

    Hi !

    I want to create an module and I want to use some Global Constant in it.
    How to I create an global constant in module what is accessable in from other modules ?

    like this example:

    *** module dirs ***
    const Const_Up=1
    const Const_Down=1

    *** module any ***
    import dirs;
    def CheckDir(Dir):
    if Dir=dirs.Const_ Up: xxx

    ?????

    Thx:
    Chris






  • Peter Hansen

    #2
    Re: Python Global Constant

    Krisztian Kepes wrote:[color=blue]
    >
    > I want to create an module and I want to use some Global Constant in it.
    > How to I create an global constant in module what is accessable in from other modules ?
    >
    > like this example:
    >
    > *** module dirs ***
    > const Const_Up=1
    > const Const_Down=1[/color]

    Just do what you did above, without the "const" modifier, which
    doesn't exist and is not really needed in Python.
    [color=blue]
    > *** module any ***
    > import dirs;
    > def CheckDir(Dir):
    > if Dir=dirs.Const_ Up: xxx[/color]

    This code should work fine, although you might want to follow
    the Python conventions for capitalization and formatting of
    your code, to make it more readable for others. For example,
    variables and functions are generally mixed case, as in checkdir
    or dir, while constants are usually ALLCAPS as in CONST_UP.

    -Peter

    Comment

    • Christoph Becker-Freyseng

      #3
      Re: Python Global Constant

      [color=blue][color=green]
      >>*** module any ***
      >>import dirs;
      >>def CheckDir(Dir):
      >> if Dir=dirs.Const_ Up: xxx[/color]
      >
      >
      > This code should work fine, although you might want to follow
      > the Python conventions ........[/color]

      What about using __builtins__ wouldn't make this the constant really global?


      cbf


      Comment

      • Ulrich Petri

        #4
        Re: Python Global Constant

        "Peter Hansen" <peter@engcorp. com> schrieb im Newsbeitrag
        news:3F0BE68B.8 93EB7E5@engcorp .com...[color=blue]
        > Krisztian Kepes wrote:
        >[color=green]
        > > *** module any ***
        > > import dirs;
        > > def CheckDir(Dir):
        > > if Dir=dirs.Const_ Up: xxx[/color]
        >
        > This code should work fine, although you might want to follow
        > the Python conventions for capitalization and formatting of
        > your code, to make it more readable for others. For example,
        > variables and functions are generally mixed case, as in checkdir
        > or dir, while constants are usually ALLCAPS as in CONST_UP.[/color]

        No it wont. "if Dir = dirs.Const_Up:" is invalid syntax (Note the = instead
        of ==)

        Ciao Ulrich


        Comment

        • Peter Hansen

          #5
          Re: Python Global Constant

          Christoph Becker-Freyseng wrote:[color=blue]
          >[color=green][color=darkred]
          > >>*** module any ***
          > >>import dirs;
          > >>def CheckDir(Dir):
          > >> if Dir=dirs.Const_ Up: xxx[/color]
          > >
          > >
          > > This code should work fine, although you might want to follow
          > > the Python conventions ........[/color]
          >
          > What about using __builtins__ wouldn't make this the constant really global?[/color]

          A module is already global, in the sense that if you do "import xxx"
          you will get a reference to a singleton module object (generally from
          xxx.py), which provides a nice clean namespace for a set of names such
          as constants.

          This makes it easy for someone reading the code to see where a constant
          is defined, and it provides a necessary level of organization.

          Putting something in __builtins__ is not only stylistically a bad
          idea for most things, but it also hides the source of the name and
          anyone reading the file will be at a loss to figure out where it
          came from unless every reference to it is preceded by a big comment::

          # WARNING! The author of this code chose the silly approach
          # of storing a reference to this constant in the __builtins__
          # namespace, which is why you can't find where it is defined.
          # This reference was stored in the initialization code that
          # is in init.py, and instead of just leaving the name there
          # so you could call it "init.CONSTANT" , it was slipped in
          # through the back door to let the author save five keystrokes,
          # at the expense of readability, but with this comment everything
          # will be okay.
          x = CONSTANT

          How is that better than using the proper approach of storing constants
          in a module, such as "constant.p y"? ;-)

          -Peter

          Comment

          • Terry Reedy

            #6
            Re: Python Global Constant

            [color=blue]
            > What about using __builtins__ wouldn't make this the constant really[/color]
            global?

            Short respone: this is an implementation-detail-dependent hack that
            Guido discourges and that Guido would be willing to break if there
            were sufficient gain otherwise.

            Longer answer: I once though of doing this too. However, the language
            reference specifies module import as the means to make objects
            globally accessible. I don't believe that the language reference
            specifies the implementation details for the builtins namespace.
            While currently
            implemented as a user-writeble dict of the {} type, bound to the name
            __builtins__, this could change.

            Terry J. Reedy


            Comment

            • Greg Ewing (using news.cis.dfn.de)

              #7
              Re: Python Global Constant

              Peter Hansen wrote:[color=blue]
              > Just do what you did above, without the "const" modifier, which
              > doesn't exist and is not really needed in Python.[/color]

              If you *really* insist on preventing anyone from changing
              them, it is possible, with some hackery. Here's one way
              that works:

              ############### ############### ############### ##########
              #
              # MyModule.py
              #

              _constants = ['PI', 'FortyTwo']

              PI = 3.1415
              FortyTwo = 42

              import types

              class _ConstModule(ty pes.ModuleType) :

              __slots__ = []

              def __setattr__(sel f, name, value):
              if name in self.__dict__['_constants']:
              raise ValueError("%s is read-only" % name)
              self.__dict__[name] = value

              del types
              import MyModule
              MyModule.__clas s__ = _ConstModule

              ############### ############### ############### ##########

              Figuring out *how* it works is left as an exercise
              for the student. :-)

              --
              Greg Ewing, Computer Science Dept,
              University of Canterbury,
              Christchurch, New Zealand


              Comment

              • Jp Calderone

                #8
                Re: Python Global Constant

                On Thu, Jul 10, 2003 at 04:06:55PM +1200, Greg Ewing (using news.cis.dfn.de ) wrote:[color=blue]
                > Peter Hansen wrote:[color=green]
                > >Just do what you did above, without the "const" modifier, which
                > >doesn't exist and is not really needed in Python.[/color]
                >
                > If you *really* insist on preventing anyone from changing
                > them, it is possible, with some hackery. Here's one way
                > that works:
                >
                > ############### ############### ############### ##########
                > #
                > # MyModule.py
                > #
                >
                > _constants = ['PI', 'FortyTwo']
                >
                > PI = 3.1415
                > FortyTwo = 42
                >
                > import types
                >
                > class _ConstModule(ty pes.ModuleType) :
                >
                > __slots__ = []
                >
                > def __setattr__(sel f, name, value):
                > if name in self.__dict__['_constants']:
                > raise ValueError("%s is read-only" % name)
                > self.__dict__[name] = value
                >
                > del types
                > import MyModule
                > MyModule.__clas s__ = _ConstModule
                >[/color]
                [color=blue][color=green][color=darkred]
                >>> import MyModule
                >>> del MyModule._const ants[:]
                >>> MyModule.PI = 'Cherry, please'
                >>> MyModule.PI[/color][/color][/color]
                'Cherry, please'

                Jp

                --
                "The problem is, of course, that not only is economics bankrupt but it has
                always been nothing more than politics in disguise ... economics is a form
                of brain damage." -- Hazel Henderson

                Comment

                • Bengt Richter

                  #9
                  Re: Python Global Constant

                  On Thu, 10 Jul 2003 02:01:47 -0400, Jp Calderone <exarkun@twiste dmatrix.com> wrote:
                  [color=blue]
                  >On Thu, Jul 10, 2003 at 04:06:55PM +1200, Greg Ewing (using news.cis.dfn.de ) wrote:[color=green]
                  >> Peter Hansen wrote:[color=darkred]
                  >> >Just do what you did above, without the "const" modifier, which
                  >> >doesn't exist and is not really needed in Python.[/color]
                  >>
                  >> If you *really* insist on preventing anyone from changing
                  >> them, it is possible, with some hackery. Here's one way
                  >> that works:
                  >>
                  >> ############### ############### ############### ##########
                  >> #
                  >> # MyModule.py
                  >> #
                  >>
                  >> _constants = ['PI', 'FortyTwo']
                  >>
                  >> PI = 3.1415
                  >> FortyTwo = 42
                  >>
                  >> import types
                  >>
                  >> class _ConstModule(ty pes.ModuleType) :
                  >>
                  >> __slots__ = []
                  >>
                  >> def __setattr__(sel f, name, value):
                  >> if name in self.__dict__['_constants']:
                  >> raise ValueError("%s is read-only" % name)
                  >> self.__dict__[name] = value
                  >>
                  >> del types
                  >> import MyModule
                  >> MyModule.__clas s__ = _ConstModule
                  >>[/color]
                  >[color=green][color=darkred]
                  > >>> import MyModule
                  > >>> del MyModule._const ants[:]
                  > >>> MyModule.PI = 'Cherry, please'
                  > >>> MyModule.PI[/color][/color]
                  > 'Cherry, please'
                  >
                  > Jp
                  >[/color]
                  Ok, this one is a little more resistant, I think (though I'm not sure how much more ;-):
                  ====< makeconst.py >============== =============== =============== =============== ==
                  import os, sys
                  def makeconst(m):
                  modulename = m.__name__
                  mpath = m.__file__
                  sfront = [
                  'def forclosure(m):' ,
                  ' dictinclosure = {'
                  ]
                  sback = [
                  ' }',
                  ' class %s(object):'% modulename,
                  ' def __getattribute_ _(self, name):',
                  ' if name=="__dict__ ": return dictinclosure.c opy()', # no mods ;-)
                  ' return dictinclosure[name]',
                  ' def __setattr__(sel f,name,val):',
                  ' raise TypeError, "module %s is read-only"'%modulena me,
                  ' return vars()["%s"]()'%modulename,
                  ''
                  ]
                  if mpath.endswith( '.pyc'): mpath = mpath[:-1]
                  if not mpath.endswith( '.py'):
                  raise ValueError, 'Not .py or .pyc based module: %s of %r'%(modulename , mpath)
                  for line in file(mpath):
                  line = line.strip()
                  if not line or line[0]=='#' or not line[0].isupper(): continue
                  lh,rh = map(str.strip, line.split('=', 1))
                  sfront.append(
                  ' %r:m.%s,'% (lh,lh) # get actual bindings from pre-constified module
                  )
                  exec '\n'.join(sfron t+sback)
                  constmod = vars()['forclosure'](m)
                  sys.modules[modulename] = constmod
                  return constmod

                  def importconst(nam e): return makeconst(__imp ort__(name))
                  =============== =============== =============== =============== =============== ======

                  and we'll import and "make constant" the module:

                  ====< MyConsts.py >============== =============== =======
                  ############### ############### ############### ##########
                  #
                  # MyConsts.py
                  #

                  PI = 3.1415
                  FortyTwo = 42
                  =============== =============== =============== ==========[color=blue][color=green][color=darkred]
                  >>> import makeconst
                  >>> MyConsts = makeconst.impor tconst('MyConst s')
                  >>> MyConsts.PI[/color][/color][/color]
                  3.1415000000000 002[color=blue][color=green][color=darkred]
                  >>> dir(MyConsts)[/color][/color][/color]
                  ['FortyTwo', 'PI'][color=blue][color=green][color=darkred]
                  >>> MyConsts.FortyT wo[/color][/color][/color]
                  42[color=blue][color=green][color=darkred]
                  >>> MyConsts.FortyT wo = 43[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  File "<string>", line 11, in __setattr__
                  TypeError: module MyConsts is read-only[color=blue][color=green][color=darkred]
                  >>> setattr(MyConst s,'foo',123)[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  File "<string>", line 11, in __setattr__
                  TypeError: module MyConsts is read-only[color=blue][color=green][color=darkred]
                  >>> MyConsts.__dict __[/color][/color][/color]
                  {'PI': 3.1415000000000 002, 'FortyTwo': 42}[color=blue][color=green][color=darkred]
                  >>> MyConsts.__dict __['PI'] = 'Cherry?'
                  >>> MyConsts.__dict __[/color][/color][/color]
                  {'PI': 3.1415000000000 002, 'FortyTwo': 42}[color=blue][color=green][color=darkred]
                  >>> vars(MyConsts)[/color][/color][/color]
                  {'PI': 3.1415000000000 002, 'FortyTwo': 42}[color=blue][color=green][color=darkred]
                  >>> MyConsts.PI[/color][/color][/color]
                  3.1415000000000 002

                  [color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'__dict__')[/color][/color][/color]
                  {}[color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'__class__')[/color][/color][/color]
                  <class 'makeconst.MyCo nsts'>[color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'__class__') .__dict__[/color][/color][/color]
                  <dict-proxy object at 0x007DD6F0>[color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'__class__') .__dict__.keys( )[/color][/color][/color]
                  ['__module__', '__dict__', '__getattribute __', '__weakref__', '__setattr__', '__doc__'][color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'PI')[/color][/color][/color]
                  Traceback (most recent call last):
                  File "<stdin>", line 1, in ?
                  AttributeError: 'MyConsts' object has no attribute 'PI'

                  Well, we can force one that will come back that way[color=blue][color=green][color=darkred]
                  >>> object.__setatt r__(MyConsts,'P I','Cherry ;-)')[/color][/color][/color]

                  Not this way:[color=blue][color=green][color=darkred]
                  >>> MyConsts.PI[/color][/color][/color]
                  3.1415000000000 002

                  But this way:[color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'PI')[/color][/color][/color]
                  'Cherry ;-)'

                  We can see it in the instance dict that was created:[color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'__dict__')[/color][/color][/color]
                  {'PI': 'Cherry ;-)'}

                  But not via the object normally:[color=blue][color=green][color=darkred]
                  >>> dir(MyConsts)[/color][/color][/color]
                  ['FortyTwo', 'PI'][color=blue][color=green][color=darkred]
                  >>> MyConsts.__dict __[/color][/color][/color]
                  {'PI': 3.1415000000000 002, 'FortyTwo': 42}[color=blue][color=green][color=darkred]
                  >>> getattr(MyConst s,'__dict__')[/color][/color][/color]
                  {'PI': 3.1415000000000 002, 'FortyTwo': 42}

                  So you can force the instance to get a __dict__ with whatever apparent attribute, but you
                  can't make it apparent via normal attribute access, so it wouldn't affect modules importing
                  and using MyConsts normally:
                  [color=blue][color=green][color=darkred]
                  >>> MyConsts.PI[/color][/color][/color]
                  3.1415000000000 002

                  Well, some you can flesh out the special attributes/methods, but you get the drift.
                  We could also use a metaclass to fake the name exactly (when __name__ is returned ;-)
                  and in __repr__ and __str__.

                  If you import MyConsts after makeconst does its thing, I'm not sure how to sabotage the result of
                  the expression MyConsts.PI for other modules that have imported it, short of rebinding methods.
                  Since the data is not in a class variable or class dict, I you'd have to go after the closure cell.
                  I can find that (I think that's it below, though I'd have to print id(dictinclosur e) to be sure),
                  e.g.,
                  [color=blue][color=green][color=darkred]
                  >>> object.__getatt ribute__(MyCons ts,'__class__') .__getattribute __.im_func.func _closure[0][/color][/color][/color]
                  <cell at 0x007D8FB0: dict object at 0x007DD5E0>

                  but how do you get at the dict in the cell? I don't guess it should be allowed, even if it's possible.

                  Otherwise you'll just have to mess with sys.modules similarly to get around it, I think, or accept
                  that you just have constant bindings (maybe to mutable objects though ;-)

                  Regards,
                  Bengt Richter

                  Comment

                  • Christoph Becker-Freyseng

                    #10
                    Re: Python Global Constant; __builtins__

                    Hello,

                    Maybe I missunderstood the OP. So I said that __builtins__ might be
                    useful. I know that you should not use it in most cases because it makes
                    code less readable (where is xy defined?) and might cause unwanted
                    side-effects.
                    However e.g. if you're programming a big framework like Zope it is useful.

                    cbf




                    Comment

                    Working...