Как мне реализовать Java-подобное перечисление в Python? - PullRequest
1 голос
/ 26 июля 2011

Что такое версия Python, чтобы сказать это .. это в Java

public static enum Operations {Add, Subtract, Multiply, Divide, None};

Я конвертирую всю программу в Python, я просто не могу понять эту часть

вот мойвесь класс

    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;
    }
}

Ответы [ 7 ]

7 голосов
/ 26 июля 2011

Вы всегда можете использовать 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

В новых версиях Python нельзя присвоить None, поэтому я изменил его на None_.

6 голосов
/ 26 июля 2011

Python не имеет класса enum. Он просто использует обычные целые числа. Самый простой способ сделать шаблон частью класса - это сделать следующее:

class Operation:
    ADD, SUBTRACT, MULTIPLY, DIVIDE, NONE = range(5)

, который назначит добавление 0 и ни одного 4. Это самый чистый способ сделать это (и это гарантирует, что у вас нет последовательностей в этой последовательности, которые бы имели одинаковое число, и что пропустил присвоение чего-либо одному из номеров.

5 голосов
/ 26 июля 2011

В Python любой атрибут или метод считается открытым, если вы не ставите подчеркивание в начале его имени. Вот соответствующий раздел учебника по Python 2.7 .

В Python нет способа точно дублировать функцию static, но любые атрибуты, которые вы определяете в классе, будутвидны в случаях так же, как static переменные.Просто attribute = value в вашем определении класса, и все в порядке.

Вы не можете делать значения constant в Python, но соглашение заключается в использовании UPPERCASE_IDENTIFIERS для обозначения этого намерения.

Перечисления не существуют.В Python для этой цели обычно используются обычные строковые константы.Просто передайте "add" "subtract", "multiply", "divide" или None вашей функции.

Например, в вашем парсере

if (operator.equals("+"))
    op = Expression.Operations.Add;

станет

if operator == "+":
    op = "add"

и в вашем оценщике

if (op == Expression.Operations.Add)
    value = a + b;

станет

if op == "add"
    value = a + b
3 голосов
/ 26 июля 2011

Диктовка может обеспечить отображение между символом и функцией. Модуль operator обеспечивает удобный доступ к встроенным функциям, используемым в выражениях. Кроме того, вы можете защитить некоторые атрибуты от случайного изменения из-за глючного кода, сделав их доступными только для чтения. Попытка изменить их вызовет ошибку AttributeError во время выполнения. Если кому-то действительно нужен доступ для записи, он все еще доступен через префиксные переменные с подчеркиванием, но это закрытый интерфейс.

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)
2 голосов
/ 26 июля 2011

лучший способ сделать это будет выглядеть так:

class Operations:
    Add=1
    Subtract=2
    Multiply=3
    Divide=4
    None=5
0 голосов
/ 26 июля 2011

Мне нравятся перечисления, и мне бы хотелось, чтобы у Python были какие-то официальные перечисления.

Вот ссылка на другой ответ, который я написал о перечислениях Python:

Как я могу представить'Enum' в Python?

И вот прямая ссылка на рецепт, который я рекомендую там:

http://code.activestate.com/recipes/413486/

0 голосов
/ 26 июля 2011

перечисления в Java полагаются на http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern - перечисления в Java похожи на: Enum>. поэтому, если Python не поддерживает такие вещи, вам, возможно, придется использовать что-то вроде
Типовое перечисление Enum Pattern: http://java.sun.com/developer/Books/effectivejava/Chapter5.pdf

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...