【问题标题】:Allowing User to Input Variables (Python)允许用户输入变量 (Python)
【发布时间】:2012-12-06 20:25:27
【问题描述】:

我正在使用 PuLP 开发一个项目,我正在尝试创建一个终端提示符以允许用户输入他们的数据,然后我的 Python 程序会将输入更改为 PuLP 可读的代码。为此,我必须允许用户输入:

2*a + 3*b <= c

我的代码将 eval() 这段代码以及创建变量 a、b 和 c

a = LpVariable("a",None,None,LpContinuous)
b = LpVariable("b",None,None,LpContinuous)
c = LpVariable("c",None,None,LpContinuous)

有什么想法吗?我试过使用 exec() 但它似乎不太喜欢。

目前我通过以下方式获得输入:

print "Please enter your constraints 1 at a time and enter '#' when done:"
control = True
while (control):
    entry = raw_input('-->')
    entryS = ""
    entryS += entry

所以字符串 2*a+3*B

【问题讨论】:

  • 你现在如何从终端获取输入?
  • 我首先将整个内容作为字符串输入,然后您必须检查每个“字母”以查看它是否为 char、int oder 运算符,然后声明一个匹配的变量。
  • @usmcs 更新了问题,抱歉。
  • 每次都会删除条目。
  • @user1880863 如果我不知道要说什么,我如何声明一个匹配变量它可能是 2*bla + 3*anystring

标签: python input pulp


【解决方案1】:

使用eval() 可能不是一个好主意,但如果你坚持(Python 3):

call = lambda f: lambda *args: f(*args)
flip = lambda f: lambda *args: f(*reversed(args))


class Expression:

    def __repr__(self):
        return '{}({})'.format(type(self).__name__, self)


class BinaryExpression(Expression):

    def __init__(self, left, right):
        self.left = promote(left)
        self.right = promote(right)

    def __str__(self):
        return '({} {} {})'.format(self.op, self.left, self.right)


class Variable(Expression):

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name


class Number(Expression):

    def __init__(self, value):
        self.value = int(value)

    def __str__(self):
        return str(self.value)


class Multiplication(BinaryExpression):
    op = '*'


class Addition(BinaryExpression):
    op = '+'


class Smaller(BinaryExpression):
    op = '<'


class Greater(BinaryExpression):
    op = '>'


class SmallerOrEqual(BinaryExpression):
    op = '<='


class GreaterOrEqual(BinaryExpression):
    op = '>='


Expression.__mul__ = call(Multiplication)
Expression.__rmul__ = flip(Multiplication)
Expression.__add__ = call(Addition)
Expression.__radd__ = flip(Addition)
Expression.__lt__ = call(Smaller)
Expression.__gt__ = call(Greater)
Expression.__le__ = call(SmallerOrEqual)
Expression.__ge__ = call(GreaterOrEqual)


def promote(item):
    if isinstance(item, str):
        return Variable(item)
    elif isinstance(item, int):
        return Number(item)
    else:
        return item


class LpVariable:

    def __init__(self, name, x, y, z):
        self.name = name
        self.x = x
        self.y = y
        self.z = z

    def __str__(self):
        return 'LpVariable({}, {}, {}, {})'.format(
            self.name,
            self.x,
            self.y,
            self.z,
        )

    __repr__ = __str__


LpContinuous = 'LpContinuous'


class ExpressionVisitor:

    def visit(self, node):
        return getattr(self, 'visit_' + type(node).__name__)(node)


class LpTransformer(ExpressionVisitor):

    def visit_Variable(self, node):
        return LpVariable(node.name, None, None, LpContinuous)

    def visit_Number(self, node):
        return node.value

    def visit_Multiplication(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_Addition(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_Smaller(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_Greater(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_SmallerOrEqual(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_GreaterOrEqual(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]


class Evaluator(ExpressionVisitor):

    def __init__(self, **env):
        self.env = env

    def visit_Variable(self, node):
        return self.env[node.name]

    def visit_Number(self, node):
        return node.value

    def visit_Multiplication(self, node):
        return self.visit(node.left) * self.visit(node.right)

    def visit_Addition(self, node):
        return self.visit(node.left) + self.visit(node.right)

    def visit_Smaller(self, node):
        return self.visit(node.left) < self.visit(node.right)

    def visit_Greater(self, node):
        return self.visit(node.left) > self.visit(node.right)

    def visit_SmallerOrEqual(self, node):
        return self.visit(node.left) <= self.visit(node.right)

    def visit_GreaterOrEqual(self, node):
        return self.visit(node.left) >= self.visit(node.right)


class Namespace(dict):

    def __missing__(self, key):
        value = self[key] = Variable(key)
        return value


def main():
    constraints = '2*a + 3*b <= c'
    namespace = Namespace()
    tree = eval(constraints, {}, namespace)
    print('AST in prefix notation:', tree)
    print()
    print('Namespace:', namespace)
    print()
    print('LP-Transformed tree:')
    import pprint
    pprint.pprint(LpTransformer().visit(tree))
    print()
    print('Evaluated with a=3, b=5, c=10:')
    pprint.pprint(Evaluator(a=3, b=5, c=10).visit(tree))
    print()
    print('Evaluated with a=3, b=5, c=100:')
    pprint.pprint(Evaluator(a=3, b=5, c=100).visit(tree))


if __name__ == '__main__':
    main()

结果:

AST in prefix notation: (<= (+ (* 2 a) (* 3 b)) c)    

Namespace: {'a': Variable(a), 'c': Variable(c), 'b': Variable(b)}

LP-Transformed tree:
['<=',
 ['+',
  ['*', 2, LpVariable(a, None, None, LpContinuous)],
  ['*', 3, LpVariable(b, None, None, LpContinuous)]],
 LpVariable(c, None, None, LpContinuous)]

Evaluated with a=3, b=5, c=10:
False

Evaluated with a=3, b=5, c=100:
True

LpVariable 类显然是一个模型。此外,LpTransformer 类应该产生可供纸浆使用的东西。只需相应地更改 visit_* 方法即可。

数字都是ints,你可能不想要。您可能应该添加floats 和/或将所有数字转换为decimal.Decimal

我可能会编写一个真正的解析器,而不是使用eval(),也许使用 pyparsing,或者,我最喜欢的类似的东西,Parcon。

【讨论】:

    【解决方案2】:

    entryS = "" 
    

    在while循环之前。

    【讨论】:

    • 用户将一次为 PuLP(python 的线性编程包)输入一组约束。但是,PuLP 需要您单独声明变量,因此我想遍历输入以尝试查找变量并将它们放入第二种类型的代码中。对不起,如果我解释得不好,我是新手。因此必须为每个输入重置 entryS。
    猜你喜欢
    • 2016-10-13
    • 2021-02-08
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    相关资源
    最近更新 更多