What do you use as symbols for Python ?

Discussion in 'Python' started by Pierre Barbier de Reuille, Nov 10, 2005.

  1. When you need some symbols in your program, what do you use in Python ?

    For example, an object get a state. This state is more readable if
    expressed as a symbols, for example "opened", "closed", "error".
    Typically, in C or C++, I would use an enum for that:
    enum OBJECT_STATE
    {
    opened, closed, error
    }

    In CAML or Haskell I would use the union types:

    type ObjectState = Opened | Closed | Error

    In Ruby I would use the symbols :

    object.state = :eek:pened
    object.state = :closed
    object.state = :error

    .... but I don't know what to use in Python !

    Thanks,

    Pierre
     
    Pierre Barbier de Reuille, Nov 10, 2005
    #1
    1. Advertising

  2. Pierre Barbier de Reuille wrote:

    > When you need some symbols in your program, what do you use in Python ?
    >
    > For example, an object get a state. This state is more readable if
    > expressed as a symbols, for example "opened", "closed", "error".
    > Typically, in C or C++, I would use an enum for that:
    > enum OBJECT_STATE
    > {
    > opened, closed, error
    > }


    OPENED, CLOSED, ERROR = range(3)

    object.state = OPENED

    --
    Erik Max Francis && && http://www.alcyone.com/max/
    San Jose, CA, USA && 37 20 N 121 53 W && AIM erikmaxfrancis
    Whoever named it necking was a poor judge of anatomy.
    -- Groucho Marx
     
    Erik Max Francis, Nov 10, 2005
    #2
    1. Advertising

  3. "Erik Max Francis" <> wrote:

    > Pierre Barbier de Reuille wrote:
    >
    > > When you need some symbols in your program, what do you use in Python ?
    > >
    > > For example, an object get a state. This state is more readable if
    > > expressed as a symbols, for example "opened", "closed", "error".
    > > Typically, in C or C++, I would use an enum for that:
    > > enum OBJECT_STATE
    > > {
    > > opened, closed, error
    > > }

    >
    > OPENED, CLOSED, ERROR = range(3)
    >
    > object.state = OPENED


    Or if you want something closer to real enumerations, there are several
    recipes in the cookbook.
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413486 seems to
    be pretty good according to the ratings.

    George
     
    George Sakkis, Nov 10, 2005
    #3
  4. Pierre Barbier de Reuille wrote:
    > When you need some symbols in your program, what do you use in Python ?
    >
    > For example, an object get a state. This state is more readable if
    > expressed as a symbols, for example "opened", "closed", "error".
    > Typically, in C or C++, I would use an enum for that:
    > enum OBJECT_STATE
    > {
    > opened, closed, error
    > }
    >
    > In CAML or Haskell I would use the union types:
    >
    > type ObjectState = Opened | Closed | Error
    >
    > In Ruby I would use the symbols :
    >
    > object.state = :eek:pened
    > object.state = :closed
    > object.state = :error
    >
    > ... but I don't know what to use in Python !


    Depends on the job... If I need to do bitmask operations, I'll use
    integer flags. If I want the symbol to be human-readable, I'll use
    strings. But everything in Python being an object, you can use whatever
    seems appropriate....

    Since we're in a 'state' exemple, here's a possible state pattern
    implementation:

    class MyObject(object):
    def __init__(self, name):
    self.name = name
    self.__class__ = ClosedState

    state = property(fget=lambda self: self.__class__)

    def open(self, arg):
    if arg == 1:
    self.__class__ = OpenedState
    else:
    self.__class__ = ErrorState

    def close(self):
    self.__class__ = ClosedState


    class OpenedState(MyObject):pass
    class ClosedState(MyObject):pass
    class ErrorState(MyObject):pass

    m = MyObject('toto')
    assert m.state is ClosedState
    m.open(1)
    assert m.state is OpenedState
    m.close()
    assert m.state is ClosedState
    m.open(2)
    assert m.state is ErrorState

    I made states 'dummy' objects, but you could make this a real state
    pattern implementation by defining default methods in the base class and
    overriding appropriate methods in the 'state' subclasses.

    HTH
    --
    bruno desthuilliers
    python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
    p in ''.split('@')])"
     
    bruno at modulix, Nov 10, 2005
    #4
  5. Op 2005-11-10, Pierre Barbier de Reuille schreef <>:
    > When you need some symbols in your program, what do you use in Python ?
    >
    > For example, an object get a state. This state is more readable if
    > expressed as a symbols, for example "opened", "closed", "error".
    > Typically, in C or C++, I would use an enum for that:
    > enum OBJECT_STATE
    > {
    > opened, closed, error
    > }
    >
    > In CAML or Haskell I would use the union types:
    >
    > type ObjectState = Opened | Closed | Error
    >
    > In Ruby I would use the symbols :
    >
    > object.state = :eek:pened
    > object.state = :closed
    > object.state = :error
    >
    > ... but I don't know what to use in Python !


    I sometimes just use a class per symbol

    class Opened: pass
    class Closed: pass
    class Error: pass

    --
    Antoon Pardon
     
    Antoon Pardon, Nov 10, 2005
    #5
  6. Pierre Barbier de Reuille

    Gary Herron Guest

    Erik Max Francis wrote:

    >Pierre Barbier de Reuille wrote:
    >
    >
    >
    >>When you need some symbols in your program, what do you use in Python ?
    >>
    >>For example, an object get a state. This state is more readable if
    >>expressed as a symbols, for example "opened", "closed", "error".
    >>Typically, in C or C++, I would use an enum for that:
    >>enum OBJECT_STATE
    >>{
    >> opened, closed, error
    >>}
    >>
    >>

    >
    > OPENED, CLOSED, ERROR = range(3)
    >
    > object.state = OPENED
    >
    >

    Another similar approach that keeps those values together in a single
    namespace is this (my favorite):

    class State:
    OPENED, CLOSED, ERROR = range(3)

    Then you can refer to the values as
    State.OPENED
    State.CLOSED
    State.ERROR

    The extra clarity (and slight wordiness) of the dotted notation seems,
    somehow, quite Pythonic to me.

    Gary Herron



    --
    Gary Herron, PhD.
    Department of Computer Science
    DigiPen Institute of Technology
    (425) 895-4418
     
    Gary Herron, Nov 10, 2005
    #6
  7. Well, thank you all !

    I still feel it could be good for Python to have some kind of symbols
    built in, and I will try to expose that to the python-dev list, to see
    their reaction.

    But in the different solutions proposed, the one I prefer is probably
    the definitions of contants in a class to group them. Simple and
    organized, I like it.

    Thanks,

    Pierre
     
    Pierre Barbier de Reuille, Nov 10, 2005
    #7
  8. Pierre Barbier de Reuille wrote:
    > Well, thank you all !
    >
    > I still feel it could be good for Python to have some kind of symbols
    > built in, and I will try to expose that to the python-dev list, to see
    > their reaction.
    >
    > But in the different solutions proposed, the one I prefer is probably
    > the definitions of contants in a class to group them. Simple and
    > organized, I like it.
    >
    > Thanks,
    >
    > Pierre

    A suggestion: There are enough PyDev-ers who read this list that you
    needn't bother talking over there (it will be resented). If you want
    to pursue it farther, either submit an RFE with a fairly thorough
    explanation of why this is useful, or write and carry a PEP through
    about it. This suggestion is neither new nor unique (many people
    used to other languages suggest it as they come to Python), so you
    probably will have to have quite persuasive arguments.

    --Scott David Daniels
     
    Scott David Daniels, Nov 10, 2005
    #8
  9. I use custom classes and the "is" operator... that way, things don't
    get confused with integers, and I have an object where repr(state) will
    give me more than an integer. (the integer approach works well enough
    but seems like a case of "I can program C in ANY language!")

    opened = type('opened', (object,), {})
    closed = type('closed', (object,), {})
    error = type('closed', (object,), {})

    if thing.state is opened:
    ...
    elif thing.state is error:
    ... etc
     
    Lonnie Princehouse, Nov 10, 2005
    #9
  10. Gary Herron <> wrote:
    >Another similar approach that keeps those values together in a single
    >namespace is this (my favorite):
    >
    > class State:
    > OPENED, CLOSED, ERROR = range(3)
    >
    >Then you can refer to the values as
    > State.OPENED
    > State.CLOSED
    > State.ERROR
    >
    >The extra clarity (and slight wordiness) of the dotted notation seems,
    >somehow, quite Pythonic to me.


    I have here an implementation (written by a colleague) of a whole pile
    of such -- in this particular case it's helpful to do it in this style
    rather than the class OPENED: pass because the values are coming from/
    going to a database. And it goes a little further, with

    class State:
    Enum = range(3)
    OPENED, CLOSED, ERROR = Enum
    Names = { OPENED: "OPENED", CLOSED: "CLOSED", ERROR: "ERROR" }

    so you can used State.Names[state] to provide something user-readable,
    and state in State.Enum to check data consistency. (OK, that probably
    doesn't make much sense with this particular State, but it does when
    your getting value-as-number from an external source.)

    --
    \S -- -- http://www.chaos.org.uk/~sion/
    ___ | "Frankly I have no feelings towards penguins one way or the other"
    \X/ | -- Arthur C. Clarke
    her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump
     
    Sion Arrowsmith, Nov 11, 2005
    #10
  11. Sion Arrowsmith wrote:
    ....
    > class State:
    > Enum = range(3)
    > OPENED, CLOSED, ERROR = Enum
    > Names = { OPENED: "OPENED", CLOSED: "CLOSED", ERROR: "ERROR" }


    > so you can used State.Names[state] to provide something user-readable, ...


    Or use a function like:

    def named(value, classes):
    for klass in classes:
    for name, val in vars(klass).iteritems():
    if val == value:
    return name
    raise ValueError, "No names for %r in %s" (value, classes)

    Remember CPU time is almost free when it is associated with a line
    typed to a user paying attention. This way you (A) don't have
    to repeat the names in the source (a great place for errors),
    and (B) you can say to yourself, "I think this is in one of these
    several things" and go hunting happily.

    In our example, named(2, [State]) gives us "ERROR"

    --
    -Scott David Daniels
     
    Scott David Daniels, Nov 11, 2005
    #11
  12. Pierre Barbier de Reuille

    Daniel Evers Guest

    Hi!

    Never would have thought of this...
    I mixed this with the class-version and created a new class derived from
    "str" for easier printing and added an iterator:

    ---

    class Enum:
    class Type(str):
    def __init__(self, name):
    self.__name = name
    def __str__(self):
    return self.__name

    def __init__(self, *keys):
    self.__keys = []
    for key in keys:
    mytype = self.Type(key)
    self.__dict__[key] = mytype
    self.__keys.append(mytype)
    self.__index = -1
    self.__count = len(keys)

    def __iter__(self):
    return self

    def next(self):
    self.__index = self.__index + 1
    if (self.__index >= self.__count):
    self.__index = -1
    raise StopIteration
    return self.__keys[self.__index]

    friends = Enum("Eric", "Kyle", "Stan", "Kenny")
    print "These are my friends:",
    print ", ".join([kid for kid in friends])
    for kid in friends:
    print kid,
    if kid is friends.Kenny:
    print "dead"
    else:
    print "alive"
    ---

    Daniel
     
    Daniel Evers, Nov 11, 2005
    #12
  13. Pierre Barbier de Reuille

    gsteff Guest

    I've seen the following style in some code (the formencode library
    comes to mind):

    opened = object()
    closed = object()
    error = object()

    Greg
     
    gsteff, Nov 11, 2005
    #13
  14. Re: What do you use as symbols for Python?

    Gary Herron <> writes:

    > Another similar approach that keeps those values together in a single
    > namespace is this (my favorite):
    >
    > class State:
    > OPENED, CLOSED, ERROR = range(3)
    >
    > Then you can refer to the values as
    > State.OPENED
    > State.CLOSED
    > State.ERROR


    Of course, with this solution you still get this problem:

    class State:
    OPENED, CLOSED, ERROR = range(3)

    class Spam:
    EGGS, HAM, TOAST = range(3)

    State.ERROR == Spam.TOAST => True

    Thus, the solutions using unique objects for each value seems cleaner,
    and closer to actual symbols, to me.

    I don't see why Python doesn't go all the way and add a real symbol
    type, though. I've seen way too many ugly string or integer based
    solutions.

    --
    Björn Lindström <>
    Student of computational linguistics, Uppsala University, Sweden
     
    =?utf-8?Q?Bj=C3=B6rn_Lindstr=C3=B6m?=, Nov 11, 2005
    #14
  15. Pierre Barbier de Reuille

    Peter Otten Guest

    Daniel Evers wrote:

    > I mixed this with the class-version and created a new class derived from
    > "str" for easier printing and added an iterator:
    >
    > ---
    >
    > class Enum:
    > class Type(str):
    > def __init__(self, name):
    > self.__name = name
    > def __str__(self):
    > return self.__name
    >
    > def __init__(self, *keys):
    > self.__keys = []
    > for key in keys:
    > mytype = self.Type(key)
    > self.__dict__[key] = mytype
    > self.__keys.append(mytype)


    You should ditch what follows and instead add just

    def __iter__(self):
    return iter(self.__keys)

    > self.__index = -1
    > self.__count = len(keys)
    >
    > def __iter__(self):
    > return self
    >
    > def next(self):
    > self.__index = self.__index + 1
    > if (self.__index >= self.__count):
    > self.__index = -1
    > raise StopIteration
    > return self.__keys[self.__index]
    >
    > friends = Enum("Eric", "Kyle", "Stan", "Kenny")
    > print "These are my friends:",
    > print ", ".join([kid for kid in friends])
    > for kid in friends:
    > print kid,
    > if kid is friends.Kenny:
    > print "dead"
    > else:
    > print "alive"
    > ---


    To see the problem with your original code (an object serving as its own
    iterator) try the following example:

    friends = Enum("Eric", "Kyle", "Stan", "Kenny")
    if "Kyle" in friends:
    print "Hi Kyle"
    print "My friends:", ", ".join(friends)

    Only Stan and Kenny show up in the last print statement because the
    containment test did not iterate over all friends.

    Also, Type.__name seems redundant. Just

    class Type(str): pass

    should do the job.

    Peter
     
    Peter Otten, Nov 12, 2005
    #15
  16. Pierre Barbier de Reuille

    Chris Smith Guest

    >>>>> "Gary" == Gary Herron <> writes:

    Gary> Erik Max Francis wrote:
    >> Pierre Barbier de Reuille wrote: > > >
    >>When you need some symbols in your program, what do you use in
    >> Python ?
    >>>
    >>> For example, an object get a state. This state is more
    >>> readable if expressed as a symbols, for example "opened",
    >>> "closed", "error". Typically, in C or C++, I would use an
    >>> enum for that: enum OBJECT_STATE { opened, closed, error
    >>> }
    >>>
    >>>

    >>

    > OPENED, CLOSED, ERROR = range(3)
    >>
    >> object.state = OPENED
    >>
    >>

    Gary> Another similar approach that keeps those values together in
    Gary> a single namespace is this (my favorite):

    Gary> class State: OPENED, CLOSED, ERROR = range(3)

    Gary> Then you can refer to the values as State.OPENED
    Gary> State.CLOSED State.ERROR

    Gary> The extra clarity (and slight wordiness) of the dotted
    Gary> notation seems, somehow, quite Pythonic to me.

    Gary> Gary Herron

    I think Zoran Isailovski has the last word on the topic:
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413486
     
    Chris Smith, Nov 12, 2005
    #16
  17. Pierre Barbier de Reuille

    Daniel Evers Guest

    Peter Otten wrote:
    >
    > You should ditch what follows and instead add just
    >
    > def __iter__(self):
    > return iter(self.__keys)


    Mhh. I should start learning the builtins ... :)

    > To see the problem with your original code (an object serving as its own
    > iterator) try the following example:
    >
    > friends = Enum("Eric", "Kyle", "Stan", "Kenny")
    > if "Kyle" in friends:
    > print "Hi Kyle"
    > print "My friends:", ", ".join(friends)
    >
    > Only Stan and Kenny show up in the last print statement because the
    > containment test did not iterate over all friends.


    Never would have thought of this... Makes it even easier.

    > Also, Type.__name seems redundant. Just
    >
    > class Type(str): pass
    >
    > should do the job.


    Right, works just fine. I'm not used to types, meanwhile I replaced
    Type(str) by a simple class Type, works as well.

    Thanks a lot, I was starting to integrate this solution in my code, now I
    can fix it before it's even used :)

    Daniel
     
    Daniel Evers, Nov 12, 2005
    #17
    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. Doris Cox
    Replies:
    0
    Views:
    562
    Doris Cox
    Dec 2, 2003
  2. Dennis
    Replies:
    0
    Views:
    706
    Dennis
    Dec 2, 2003
  3. Dennis
    Replies:
    0
    Views:
    462
    Dennis
    Dec 2, 2003
  4. pek
    Replies:
    0
    Views:
    1,236
  5. johannes falcone
    Replies:
    6
    Views:
    1,014
    johannes falcone
    May 16, 2013
Loading...

Share This Page