Re: pep 8 constants

Discussion in 'Python' started by Brendan Miller, Jan 14, 2009.

  1. > FOO = 1
    >
    > def f(x=FOO):
    > ...
    >
    >
    > Use this instead:
    >
    > def f(x=1):
    > ...



    I tend to use constants as a means of avoiding the proliferation of
    magic literals for maintenance reasons... Like say if your example of
    FOO would have been used in 10 places. Maybe it is more pythonic to
    simply denote such a thing as simply a normal variable? That doesn't
    seem to give a hint that it shouldn't be assigned a second time.
    Brendan Miller, Jan 14, 2009
    #1
    1. Advertising

  2. On Tue, 13 Jan 2009 23:26:54 -0800, Brendan Miller wrote:

    > I tend to use constants as a means of avoiding the proliferation of
    > magic literals for maintenance reasons... Like say if your example of
    > FOO would have been used in 10 places. Maybe it is more pythonic to
    > simply denote such a thing as simply a normal variable?


    But it isn't a "normal variable", it's a named constant, or at least it
    would be if Python enforced constanticity. Or constantness. Or whatever.

    > That doesn't
    > seem to give a hint that it shouldn't be assigned a second time.


    Absolutely. It's rather sad that I can do this:

    import math
    math.pi = 3.0

    I like the ability to shoot myself in the foot, thank you very much, but
    I should at least get a warning when I'm about to do so:

    math.PI = 3.0 # use God-like powers to change a constant




    Changing the laws of physics, one fundamental constant at a time-ly y'rs,

    --
    Steven
    Steven D'Aprano, Jan 14, 2009
    #2
    1. Advertising

  3. Brendan Miller

    MRAB Guest

    Francesco Bochicchio wrote:
    > On Wed, 14 Jan 2009 08:13:30 +0000, Steven D'Aprano wrote:
    >
    >
    >> Absolutely. It's rather sad that I can do this:
    >>
    >> import math
    >> math.pi = 3.0
    >>
    >> I like the ability to shoot myself in the foot, thank you very much, but
    >> I should at least get a warning when I'm about to do so:
    >>
    >> math.PI = 3.0 # use God-like powers to change a constant
    >>
    >>

    >
    > Constants would be a nice addition in python, sure enough.
    > But I'm not sure that this can be done without a run-time check every time
    > the constant is used, and python is already slow enough. Maybe a check
    > that is disabled when running with optimizing flags ?
    >
    > But I'm sure this discussion has been already made and the FINAL WORD has
    > been already spoken.
    >
    >>> class Constants(object):

    def __setattr__(self, key, value):
    if key in self.__dict__:
    raise ValueError("Can't change constant")
    self.__dict__[key] = value


    >>> c = Constants()
    >>> c.PI = 3.0
    >>> c.PI

    3.0
    >>> c.PI = 4.0


    Traceback (most recent call last):
    File "<pyshell#22>", line 1, in <module>
    c.PI = 4.0
    File "<pyshell#19>", line 4, in __setattr__
    raise ValueError("Can't change constant")
    ValueError: Can't change constant
    MRAB, Jan 18, 2009
    #3
  4. > Constants would be a nice addition in python, sure enough.

    My original question was about PEP-8 and whether it is pythonic to use
    all caps to denote a variable that shouldn't be changed. More of a
    style question than a language question.

    I actually think *enforcing* constantness seems to go against the
    grain of the language so to speek
    Brendan Miller, Jan 20, 2009
    #4
  5. On Mon, 19 Jan 2009 19:11:16 -0800, Brendan Miller wrote:

    >> Constants would be a nice addition in python, sure enough.

    >
    > My original question was about PEP-8 and whether it is pythonic to use
    > all caps to denote a variable that shouldn't be changed. More of a style
    > question than a language question.
    >
    > I actually think *enforcing* constantness seems to go against the grain
    > of the language so to speek


    Why? Python has an infinite number of constants. The only difference is
    that they are immutable objects, not names.

    But regardless... yes, it is in my opinion Pythonic to use ALLCAPS to
    designate constants (by convention). It isn't in PEP 8, but I don't think
    that matters unless PEP 8 suggests a different convention.




    --
    Steven
    Steven D'Aprano, Jan 20, 2009
    #5
  6. Brendan Miller

    Rhodri James Guest

    On Tue, 20 Jan 2009 04:58:30 -0000, Ben Finney
    <> wrote:

    > Unless someone's going to argue that “Variable Names†doesn't apply to
    > constant names, even though Python doesn't make the distinction.


    Python doesn't make the distinction, which is precisely why making the
    distinction through CONVENTIONAL_NAMING_PRACTICE is useful.

    --
    Rhodri James *-* Wildebeeste Herder to the Masses
    Rhodri James, Jan 21, 2009
    #6
  7. wrote:
    > Constants would be a nice addition in python, sure enough.
    > But I'm not sure that this can be done without a run-time check every time
    > the constant is used, and python is already slow enough. Maybe a check
    > that is disabled when running with optimizing flags ?
    >
    > But I'm sure this discussion has been already made and the FINAL WORD has
    > been already spoken.
    >
    > Ciao
    > ----
    > FB
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >

    One idea to make constants possible would be to extend properties to be
    able to exist at the module level as well as the class level:

    @property
    def pi():
    return 3.14159.....

    print(pi) # prints 3.14159....
    pi=32 # Raise an error Cannot set attribute ...


    Brian Vanderburg II
    Brian Allen Vanderburg II, Jan 22, 2009
    #7
  8. Brendan Miller

    Steve Holden Guest

    Brian Allen Vanderburg II wrote:
    > wrote:
    >> Constants would be a nice addition in python, sure enough.
    >> But I'm not sure that this can be done without a run-time check every
    >> time
    >> the constant is used, and python is already slow enough. Maybe a check
    >> that is disabled when running with optimizing flags ?
    >>
    >> But I'm sure this discussion has been already made and the FINAL WORD has
    >> been already spoken.
    >>
    >> Ciao
    >> ----
    >> FB
    >> --
    >> http://mail.python.org/mailman/listinfo/python-list
    >>

    > One idea to make constants possible would be to extend properties to be
    > able to exist at the module level as well as the class level:
    >
    > @property
    > def pi():
    > return 3.14159.....
    >
    > print(pi) # prints 3.14159....
    > pi=32 # Raise an error Cannot set attribute ...
    >

    I don't understand why this would print 3.14159 ... instead of <function
    __math__.pi>, or whatever.

    property would clearly have to do something very different in module
    scope in order to make this work.

    regards
    Steve
    --
    Steve Holden +1 571 484 6266 +1 800 494 3119
    Holden Web LLC http://www.holdenweb.com/
    Steve Holden, Jan 23, 2009
    #8
  9. Brendan Miller

    Ethan Furman Guest

    Steve Holden wrote:
    > Brian Allen Vanderburg II wrote:
    >
    >> wrote:
    >>
    >>>Constants would be a nice addition in python, sure enough.
    >>>But I'm not sure that this can be done without a run-time check every
    >>>time
    >>>the constant is used, and python is already slow enough. Maybe a check
    >>>that is disabled when running with optimizing flags ?
    >>>
    >>>But I'm sure this discussion has been already made and the FINAL WORD has
    >>>been already spoken.
    >>>
    >>>Ciao
    >>>----
    >>>FB

    >>
    >>One idea to make constants possible would be to extend properties to be
    >>able to exist at the module level as well as the class level:
    >>
    >>@property
    >>def pi():
    >> return 3.14159.....
    >>
    >>print(pi) # prints 3.14159....
    >>pi=32 # Raise an error Cannot set attribute ...
    >>

    >
    > I don't understand why this would print 3.14159 ... instead of <function
    > __math__.pi>, or whatever.
    >
    > property would clearly have to do something very different in module
    > scope in order to make this work.
    >
    > regards
    > Steve


    --> class tester(object):
    .... @property
    .... def pi(self):
    .... return 3.141596
    ....
    --> testee = tester()
    --> testee.pi
    3.1415959999999998

    Looks like that's how property works, so the same behavior on a module
    level would do as Brian suggests.
    --
    ~Ethan~
    Ethan Furman, Feb 25, 2009
    #9
  10. Brendan Miller

    Steve Holden Guest

    Ethan Furman wrote:
    > Steve Holden wrote:
    >> Brian Allen Vanderburg II wrote:
    >>
    >>> wrote:
    >>>
    >>>> Constants would be a nice addition in python, sure enough.
    >>>> But I'm not sure that this can be done without a run-time check every
    >>>> time
    >>>> the constant is used, and python is already slow enough. Maybe a check
    >>>> that is disabled when running with optimizing flags ?
    >>>>
    >>>> But I'm sure this discussion has been already made and the FINAL
    >>>> WORD has
    >>>> been already spoken.
    >>>>
    >>>> Ciao
    >>>> ----
    >>>> FB
    >>>
    >>> One idea to make constants possible would be to extend properties to be
    >>> able to exist at the module level as well as the class level:
    >>>
    >>> @property
    >>> def pi():
    >>> return 3.14159.....
    >>>
    >>> print(pi) # prints 3.14159....
    >>> pi=32 # Raise an error Cannot set attribute ...
    >>>

    >>
    >> I don't understand why this would print 3.14159 ... instead of <function
    >> __math__.pi>, or whatever.
    >>
    >> property would clearly have to do something very different in module
    >> scope in order to make this work.
    >>
    >> regards
    >> Steve

    >
    > --> class tester(object):
    > ... @property
    > ... def pi(self):
    > ... return 3.141596
    > ...
    > --> testee = tester()
    > --> testee.pi
    > 3.1415959999999998
    >
    > Looks like that's how property works, so the same behavior on a module
    > level would do as Brian suggests.


    But that's at the class level, not the module level.

    regards
    Steve
    --
    Steve Holden +1 571 484 6266 +1 800 494 3119
    Holden Web LLC http://www.holdenweb.com/
    Steve Holden, Feb 25, 2009
    #10
  11. En Tue, 24 Feb 2009 22:52:20 -0200, Ethan Furman <>
    escribió:

    > Steve Holden wrote:
    >> Brian Allen Vanderburg II wrote:
    >>
    >>> One idea to make constants possible would be to extend properties to be
    >>> able to exist at the module level as well as the class level:
    >>>
    >>> @property
    >>> def pi():
    >>> return 3.14159.....
    >>>
    >>> print(pi) # prints 3.14159....
    >>> pi=32 # Raise an error Cannot set attribute ...
    >>>

    >> I don't understand why this would print 3.14159 ... instead of
    >> <function
    >> __math__.pi>, or whatever.
    >> property would clearly have to do something very different in module
    >> scope in order to make this work.
    >> regards
    >> Steve

    >
    > --> class tester(object):
    > ... @property
    > ... def pi(self):
    > ... return 3.141596
    > ...
    > --> testee = tester()
    > --> testee.pi
    > 3.1415959999999998
    >
    > Looks like that's how property works, so the same behavior on a module
    > level would do as Brian suggests.


    Note that:
    - you defined the property inside the *class* tester
    - then, you created an *instance* of such class
    - you retrieve pi from the instance
    - if you retrieve pi from the class (tester.pi), you get a property
    object, not a float.
    - if you directly attach the property to the instance, testee.pi returns
    a property object, not a float.
    Finally, consider that modules are instances of type `module`; all modules
    are instances of the same type.

    How do you propose to make properties work at the module level?

    --
    Gabriel Genellina
    Gabriel Genellina, Feb 25, 2009
    #11
  12. Brendan Miller

    Steve Holden Guest

    Gabriel Genellina wrote:
    > En Tue, 24 Feb 2009 22:52:20 -0200, Ethan Furman <>
    > escribió:
    >
    >> Steve Holden wrote:
    >>> Brian Allen Vanderburg II wrote:
    >>>
    >>>> One idea to make constants possible would be to extend properties to be
    >>>> able to exist at the module level as well as the class level:
    >>>>
    >>>> @property
    >>>> def pi():
    >>>> return 3.14159.....
    >>>>
    >>>> print(pi) # prints 3.14159....
    >>>> pi=32 # Raise an error Cannot set attribute ...
    >>>>
    >>> I don't understand why this would print 3.14159 ... instead of
    >>> <function
    >>> __math__.pi>, or whatever.
    >>> property would clearly have to do something very different in module
    >>> scope in order to make this work.
    >>> regards
    >>> Steve

    >>
    >> --> class tester(object):
    >> ... @property
    >> ... def pi(self):
    >> ... return 3.141596
    >> ...
    >> --> testee = tester()
    >> --> testee.pi
    >> 3.1415959999999998
    >>
    >> Looks like that's how property works, so the same behavior on a module
    >> level would do as Brian suggests.

    >
    > Note that:
    > - you defined the property inside the *class* tester
    > - then, you created an *instance* of such class
    > - you retrieve pi from the instance
    > - if you retrieve pi from the class (tester.pi), you get a property
    > object, not a float.
    > - if you directly attach the property to the instance, testee.pi
    > returns a property object, not a float.
    > Finally, consider that modules are instances of type `module`; all
    > modules are instances of the same type.
    >
    > How do you propose to make properties work at the module level?
    >

    Thanks, Gabriel. I was beginning to think there was something terribly
    obvious I had completely missed.

    regards
    Steve
    --
    Steve Holden +1 571 484 6266 +1 800 494 3119
    Holden Web LLC http://www.holdenweb.com/
    Steve Holden, Feb 25, 2009
    #12
  13. Ben Finney a écrit :
    (snip - about using ALL_CAPS for pseudo-constants)
    > Perhaps I'd even
    > argue for an update to PEP 8 that endorses this as conventional.


    +1

    I've been a bit surprised last time I checked PEP8 to find out this
    wasn't already the case - I would have sweared it was.
    Bruno Desthuilliers, Feb 25, 2009
    #13
  14. Brian Allen Vanderburg II a écrit :
    > wrote:
    >> Constants would be a nice addition in python, sure enough.
    >> But I'm not sure that this can be done without a run-time check every
    >> time
    >> the constant is used, and python is already slow enough. Maybe a check
    >> that is disabled when running with optimizing flags ?
    >>
    >> But I'm sure this discussion has been already made and the FINAL WORD has
    >> been already spoken.
    >>
    >>

    > One idea to make constants possible would be to extend properties to be
    > able to exist at the module level as well as the class level:
    >
    > @property
    > def pi():
    > return 3.14159.....
    >
    > print(pi) # prints 3.14159....
    > pi=32 # Raise an error Cannot set attribute ...
    >


    There are a couple problems with this suggestion:

    - it would require modifying lookup rules to allow the protocol
    descriptor to be invoked on instance attributes[1] - which is not
    actually the case, by design.

    - it adds the overhead of a method and a function call for what is
    mostly a simple "constant" attribute lookup.

    FWIW, while it would already work for class-level pseudo-constants
    (using a very simple custom descriptor), I'd qualify such usage as a WTF.
    Bruno Desthuilliers, Feb 25, 2009
    #14
  15. Ethan Furman a écrit :
    > Steve Holden wrote:
    >> Brian Allen Vanderburg II wrote:
    >>

    (snip)
    >>> One idea to make constants possible would be to extend properties to be
    >>> able to exist at the module level as well as the class level:
    >>>
    >>> @property
    >>> def pi():
    >>> return 3.14159.....
    >>>
    >>> print(pi) # prints 3.14159....
    >>> pi=32 # Raise an error Cannot set attribute ...
    >>>

    >>
    >> I don't understand why this would print 3.14159 ... instead of <function
    >> __math__.pi>, or whatever.
    >>
    >> property would clearly have to do something very different in module
    >> scope in order to make this work.
    >>

    >
    > --> class tester(object):
    > ... @property
    > ... def pi(self):
    > ... return 3.141596
    > ...
    > --> testee = tester()
    > --> testee.pi
    > 3.1415959999999998
    >
    > Looks like that's how property works, so the same behavior on a module
    > level would do as Brian suggests.


    s/module/instance/

    At runtime, modules are instances of the module type - so 'module-level'
    names are really instance attributes of the module instance -, and the
    descriptor protocol is only invoked for class attributes.
    Bruno Desthuilliers, Feb 25, 2009
    #15
  16. Brendan Miller

    Robin Becker Guest

    well this sort of awful hackery will allow you to put read only constants on an
    existing module

    >>> import reportlab
    >>> reportlab.__class__
    >>> class MyModule(reportlab.__class__):

    .... @property
    .... def pi(self):
    .... return 3
    ....
    >>> z=MyModule('reportlab')
    >>> z.__dict__.update(reportlab.__dict__)
    >>> z.pi

    3
    >>> import sys
    >>> sys.modules['reportlab']=z
    >>> del reportlab
    >>> import reportlab
    >>> reportlab.pi

    3
    >>> reportlab.pi=4

    Traceback (most recent call last):
    File "<interactive input>", line 1, in <module>
    AttributeError: can't set attribute
    >>>


    so I guess if you write your own module class and then use a special importer
    you can create module like objects with read only attributes.


    --
    Robin Becker
    Robin Becker, Feb 25, 2009
    #16
  17. Robin Becker a écrit :
    > well this sort of awful hackery will allow you to put read only
    > constants on an existing module
    >

    (snip example code)
    >
    > so I guess if you write your own module class and then use a special
    > importer you can create module like objects with read only attributes.
    >


    Fine technical solution. But, err, isn't all this a bit overkill for
    something that can easily be handled by a simple convention ?-)
    Bruno Desthuilliers, Feb 25, 2009
    #17
  18. Brendan Miller

    Robin Becker Guest

    Bruno Desthuilliers wrote:
    > Robin Becker a écrit :
    >> well this sort of awful hackery will allow you to put read only
    >> constants on an existing module
    >>

    > (snip example code)
    >>
    >> so I guess if you write your own module class and then use a special
    >> importer you can create module like objects with read only attributes.
    >>

    >
    > Fine technical solution. But, err, isn't all this a bit overkill for
    > something that can easily be handled by a simple convention ?-)

    .......
    no dispute about that :)
    --
    Robin Becker
    Robin Becker, Feb 25, 2009
    #18
  19. Brendan Miller

    Rhodri James Guest

    On Wed, 25 Feb 2009 08:48:27 -0000, Bruno Desthuilliers
    <> wrote:

    > Ben Finney a écrit :
    > (snip - about using ALL_CAPS for pseudo-constants)
    >> Perhaps I'd even
    >> argue for an update to PEP 8 that endorses this as conventional.

    >
    > +1
    >
    > I've been a bit surprised last time I checked PEP8 to find out this
    > wasn't already the case - I would have sweared it was.


    It is. Aahz added it a few weeks ago.

    --
    Rhodri James *-* Wildebeeste Herder to the Masses
    Rhodri James, Feb 26, 2009
    #19
  20. Brendan Miller

    Ethan Furman Guest

    Steve Holden wrote:
    > Gabriel Genellina wrote:
    >
    >>En Tue, 24 Feb 2009 22:52:20 -0200, Ethan Furman <>
    >>escribió:
    >>
    >>
    >>>Steve Holden wrote:
    >>>
    >>>>Brian Allen Vanderburg II wrote:
    >>>>
    >>>>
    >>>>>One idea to make constants possible would be to extend properties to be
    >>>>>able to exist at the module level as well as the class level:
    >>>>>
    >>>>>@property
    >>>>>def pi():
    >>>>> return 3.14159.....
    >>>>>
    >>>>>print(pi) # prints 3.14159....
    >>>>>pi=32 # Raise an error Cannot set attribute ...
    >>>>>
    >>>>
    >>>> I don't understand why this would print 3.14159 ... instead of
    >>>><function
    >>>>__math__.pi>, or whatever.
    >>>> property would clearly have to do something very different in module
    >>>>scope in order to make this work.
    >>>> regards
    >>>> Steve
    >>>
    >>>--> class tester(object):
    >>>... @property
    >>>... def pi(self):
    >>>... return 3.141596
    >>>...
    >>>--> testee = tester()
    >>>--> testee.pi
    >>>3.1415959999999998
    >>>
    >>>Looks like that's how property works, so the same behavior on a module
    >>>level would do as Brian suggests.

    >>
    >>Note that:
    >> - you defined the property inside the *class* tester
    >> - then, you created an *instance* of such class
    >> - you retrieve pi from the instance
    >> - if you retrieve pi from the class (tester.pi), you get a property
    >>object, not a float.
    >> - if you directly attach the property to the instance, testee.pi
    >>returns a property object, not a float.
    >>Finally, consider that modules are instances of type `module`; all
    >>modules are instances of the same type.
    >>
    >>How do you propose to make properties work at the module level?
    >>

    >
    > Thanks, Gabriel. I was beginning to think there was something terribly
    > obvious I had completely missed.
    >
    > regards
    > Steve


    Yes, Thanks, Gabriel!

    You're extra comments made clarified the issue for me. Much appreciated.

    ~Ethan~
    Ethan Furman, Feb 27, 2009
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Christoph Becker-Freyseng

    PEP for new modules (I read PEP 2)

    Christoph Becker-Freyseng, Jan 15, 2004, in forum: Python
    Replies:
    3
    Views:
    369
    Gerrit Holl
    Jan 16, 2004
  2. Raymond Hettinger
    Replies:
    8
    Views:
    308
    Daniel 'Dang' Griffith
    Apr 21, 2004
  3. Raymond Hettinger
    Replies:
    0
    Views:
    311
    Raymond Hettinger
    Apr 19, 2004
  4. Lie
    Replies:
    25
    Views:
    729
    Dafydd Hughes
    Dec 18, 2007
  5. Brendan Miller

    pep 8 constants

    Brendan Miller, Jan 14, 2009, in forum: Python
    Replies:
    8
    Views:
    475
    Steven D'Aprano
    Jun 29, 2009
Loading...

Share This Page