简体   繁体   中英

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();
            //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;
    }
}

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_ .

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.

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

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

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/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM