【问题标题】:How to modify sympy's printing order?如何修改sympy的打印顺序?
【发布时间】:2017-08-10 13:58:54
【问题描述】:

我正在使用 sympy 编写代数表达式并使用它们执行基本计算。 Sympy 不跟踪变量的顺序,这在打印表达式时可能会出现问题(这个问题已经提出 herehere,所以这不是重复的)。 例如

>>> from sympy import *
>>> var("p,a")
>>> l=p-1-a;
>>> print(l);
-a+p-1

但是,sympy 似乎按字母顺序打印变量。有没有办法改变 Python 引用的字母顺序,从而欺骗 sympy 以所需的顺序打印变量?欢迎任何其他解决方案!

【问题讨论】:

  • SymPy 文档中的打印页面会有帮助吗? docs.sympy.org/latest/tutorial/printing.html
  • 我在那里没有看到任何相关的东西。这似乎是一个已知问题,我认为任何“常规”都无济于事。
  • @AlexanderMcFarlane:OP 非常了解 4 年前的问题(将它们链接起来),并且可能希望从那以后情况有所改变。以前曾向 sympy 报告过问题,不幸的是链接已损坏。我不认为这是重复的。
  • @Hannebambel 感谢您的澄清。

标签: python sympy


【解决方案1】:

感谢smichr's answer,我编写了一个自定义打印机,它可以满足我的需求。我不是一个好的程序员,所以如果你对我的代码有任何建议,我很乐意实现它们。

from sympy import *
import math
import copy
import collections
import itertools
init_printing(use_unicode=True)
var("p,a,b,c,d,e,f");
ddict=collections.OrderedDict([(p, 1),(a, 2), (b, 3), (c, 4),(d, 5),(e, 6),(f, 7),])
from sympy import Basic, Function, Symbol
from sympy.printing.printer import Printer
from sympy.printing.latex import print_latex
from sympy.core.basic import Basic
class MyPrinter(Printer):
    printmethod = '_myprinter'
    def _print_Add(self,expr):
        expr_args=expr.args
        def new_place(el):
            if el in ddict:
                return ddict[el]
            else:
                return len(ddict)+1
        def get_place(el):
            if el.is_integer:
                return new_place(el)
            elif el.is_symbol:
                return new_place(el)
            elif len(el.args)>0:
                if el.args[len(el.args)-1].is_symbol:
                    return new_place(el.args[len(el.args)-1])
                else:
                    return 0
            else:
                return 0
        def write_coeff(el):
            if el.is_integer:
                if el>0:
                    return "+%s" %el
                else:
                    return "%s" %el
            elif el.is_symbol:
                return "+%s" %el
            elif len(el.args)>0:
                if el.args[len(el.args)-1].is_symbol:
                    if el.args[0].is_rational:
                        if el.args[0]>0:
                            return "+%s" %latex(el)
                        else:
                            return "%s" %latex(el)
                    else:
                        return "%s" %latex(el)
                else:
                    return "%s" %latex(el)
            else:
                return "%s" %el
        list_place=[get_place(a) for a in expr.args]
        expr_args=zip(*sorted(zip(list_place,expr_args)))[1]
        to_print=[write_coeff(a) for a in expr_args]
        to_print[0]=str(latex(expr_args[0]))
        return "".join(a for a in to_print)
def my_printer(expr):
    return (MyPrinter().doprint(expr))
de=-a+p+3+c-b
print(my_printer(de))

【讨论】:

    【解决方案2】:

    有关创建自定义打印机的一些新文档是 in the pipe。也许这会有所帮助?我将创建一个自定义打印机——假设我们创建了一个自定义 Add 打印机——根据某些属性(如度数或项系数的符号)对 args 进行排序,然后打印生成的 Add。

    【讨论】:

    • 谢谢!如果我设法用它做点什么,我会看看,如果它有效,我会发布它。
    • 完成!我很乐意收到有关我实施您的想法的方式的任何反馈。再次感谢
    • 我最初的感觉是你做的比你需要的多。我建议您的打印方法采用两个参数:表达式和对参数进行排序的函数。然后该方法将获取参数,对它们进行排序,并将它们作为未评估的表达式传递给普通打印机。注意:在您当前的代码中,当我认为您的意思是 is_Integer 和 is_symbol 类似时,您使用 is_integer
    • 谢谢。当我有时间并更新我的答案时,我会尝试按照您的建议调整代码。
    猜你喜欢
    • 2016-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    • 2021-08-29
    • 1970-01-01
    • 2016-04-22
    相关资源
    最近更新 更多