By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,084 Members | 1,214 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,084 IT Pros & Developers. It's quick & easy.

What do you use as symbols for Python ?

P: n/a
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 = :opened
object.state = :closed
object.state = :error

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

Thanks,

Pierre
Nov 10 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a
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 && ma*@alcyone.com && 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
Nov 10 '05 #2

P: n/a
"Erik Max Francis" <ma*@alcyone.com> 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/Coo.../Recipe/413486 seems to
be pretty good according to the ratings.

George

Nov 10 '05 #3

P: n/a
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 = :opened
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 'o****@xiludom.gro'.split('@')])"
Nov 10 '05 #4

P: n/a
Op 2005-11-10, Pierre Barbier de Reuille schreef <pi************@cirad.fr>:
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 = :opened
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
Nov 10 '05 #5

P: n/a
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
Nov 10 '05 #6

P: n/a
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
Nov 10 '05 #7

P: n/a
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
sc***********@acm.org
Nov 10 '05 #8

P: n/a
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

Nov 10 '05 #9

P: n/a
Gary Herron <gh*****@digipen.edu> 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 -- si***@chiark.greenend.org.uk -- 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
Nov 11 '05 #10

P: n/a
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
sc***********@acm.org
Nov 11 '05 #11

P: n/a
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
Nov 11 '05 #12

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

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

Greg

Nov 11 '05 #13

P: n/a
Gary Herron <gh*****@digipen.edu> 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 <bk**@stp.lingfil.uu.se>
Student of computational linguistics, Uppsala University, Sweden
Nov 11 '05 #14

P: n/a
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



Nov 22 '05 #15

P: n/a
>>>>> "Gary" == Gary Herron <gh*****@digipen.edu> 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/Coo.../Recipe/413486

Nov 22 '05 #16

P: n/a
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
Nov 22 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.