How do I implement a Java-like enumeration in Python?
what is the python version of saying this.. this is in java
public static enum Operations {Add, Subtract, Multiply, Divide, None};
I am converting an entire program to python, i just cant figure out this part
heres my whole class
import java.util.*;
public class Expression
{
public static enum Operations {Add, Subtract, Multiply, Divide, None};
int a;
int b;
Expression.Operations op;
public Expression()
{
a = 0;
b = 0;
op = Expression.Operations.None;
}
public Expression(int value1, int value2, Expression.Operations operation)
{
a = value1;
b = value2;
op = operation;
}
public boolean parseString(String expressionString, Map<Character, Integer> vars)
{
Scanner scanner = new Scanner(expressionString);
//Attempt to read the first value.
if (scanner.hasNextInt())
a = scanner.nextInt();
else if (scanner.hasNext())
{
String var = scanner.next();
开发者_C百科 //Ensure that the variable identifier is a single alphabetical character in length.
if (!var.matches("[A-Z]{1}"))
{
return false;
}
if (vars.containsKey(var.charAt(0)))
a = vars.get(var.charAt(0));
else
{
System.err.println("ERROR: Uninitialized variable.");
return false;
}
}
else return false;
//If more tokens exist, attempt to read the operator.
if (scanner.hasNext())
{
String operator = scanner.next();
if (operator.equals("+"))
op = Expression.Operations.Add;
else if (operator.equals("-"))
op = Expression.Operations.Subtract;
else if (operator.equals("*"))
op = Expression.Operations.Multiply;
else if (operator.equals("/"))
op = Expression.Operations.Divide;
else
return false;
//Attempt to read the second value.
if (scanner.hasNextInt())
b = scanner.nextInt();
else if (scanner.hasNext())
{
String var = scanner.next();
//Ensure that the variable identifier is a single alphabetical character in length.
if (!var.matches("[A-Z]{1}"))
{
return false;
}
b = vars.get(var.charAt(0));
}
else return false;
}
return true;
}
public int evaluate()
{
int value = 0;
if (op == Expression.Operations.Add)
value = a + b;
if (op == Expression.Operations.Subtract)
value = a - b;
if (op == Expression.Operations.Multiply)
value = a * b;
if (op == Expression.Operations.Divide)
value = a / b;
if (op == Expression.Operations.None)
value = a;
return value;
}
}
Python doesn't have an enum class. It just does it using normal integers. The easiest way to make a template part of a class is to do the following:
class Operation:
ADD, SUBTRACT, MULTIPLY, DIVIDE, NONE = range(5)
Which will assign add to 0 and none to 4. This is the most clean way of doing it (and it will guarantee that you don't have any enums in this sequence that are the same number and that you haven't missed assigning something to one of the numbers.
You can always use a NamedTuple
>>> import collections
>>> Enum = collections.namedtuple('Enum','Add Subtract Multiply Divide None_')
>>> Enum(*range(1,6))
Enum(Add=1, Subtract=2, Multiply=3, Divide=4, None_=5)
>>> operations = _
>>> operations.Add
1
On newer Python versions, you can't assign to None
, so I changed it to None_
.
In Python any attribute or method is considered public unless you put underscores at the start of its name. Here is the relevant section in the Python 2.7 tutorial.
Python doesn't have a way of exactly duplicating the function of static
, but any attributes you define on a class will be visible in instances in the same way as static
variables are. Just attribute = value
inside your class definition and you're fine.
You can't make values constant
in Python, but the convention is to use UPPERCASE_IDENTIFIERS
to indicate that intention.
Enums do not exist. In Python ordinary strings constants are usually used for this purpose. Just pass "add"
"subtract"
, "multiply"
, "divide"
or None
to your function.
For example, in your parser
if (operator.equals("+"))
op = Expression.Operations.Add;
would become
if operator == "+":
op = "add"
and in your evaluator
if (op == Expression.Operations.Add)
value = a + b;
would become
if op == "add"
value = a + b
A dict can provide the mapping between the symbol and the function. The operator
module provides convenient access to the built-in functions used in expressions. Also, you can protect some attributes from getting accidentally modified by buggy code by making them read-only properties. Attempting to modify them will raise an AttributeError at run time. If someone really needs write access it's still available via the underscore prefixed variables, but that's a private interface.
import operator
class Expression(object):
_OP_MAP = dict((x, getattr(operator, y)) for x, y in
[('*', 'mul'), ('/', 'truediv'), ('//', 'floordiv'),
('+', 'add'), ('-', 'sub')])
_OP_MAP[None] = lambda a, b: a
a = property(lambda self: self._a) #read-only interface
b = property(lambda self: self._b)
op = property(lambda self: self._op)
def __init__(self, value1=0, value2=0, operation=None):
self._a = value1 #mutable -- we're all adults
self._b = value2
self._op = self._OP_MAP[operation]
def parse_string(self, expression_string, variables):
#...
self._op = self._OP_MAP.get(operator) #defaults to None
def evaluate(self):
return self.op(self.a, self.b)
def __repr__(self):
for k, v in self._OP_MAP.items():
if self.op == v:
return '{0} {1} {2}'.format(self.a, k, self.b)
best way to do it would be like:
class Operations:
Add=1
Subtract=2
Multiply=3
Divide=4
None=5
enums in java rely on the http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern - enums in java are like: Enum>. so unless python supports that sort of thing you may have to use something like the
Typesafe Enum Pattern: http://java.sun.com/developer/Books/effectivejava/Chapter5.pdf
I like enums and I wish Python had an official enum of some sort.
Here is a link to another answer I wrote about Python enums:
How can I represent an 'Enum' in Python?
And here's a direct link to the recipe I recommend there:
http://code.activestate.com/recipes/413486/
Python latest versions do have support for enum, just want to close the loop after reading all the above responses
https://docs.python.org/3/library/enum.html
精彩评论