如何(理智地)扩展同情配给

2024-03-28 21:42:30 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有一种合理的方法可以在sympy中得到并使用混合数而不是不正确的分数?(我使用latex输出并为有1 3/4+2 1/3=?)等问题的小学生生成PDF文件)在

我正在尝试创建一个mixedNational(或MixedNumber或MixedFraction)类,以便在SymPy中使用。 This是我能找到的唯一与SymPy中的混合表示相关的线程。在

我希望我的MixedRational类有两个成员变量:I和f,用于混合数的整数部分和小数部分,并具有适当的方法,如__str__,以便将其打印为混合数。在

然而,我无法克服这条道路上的第一个障碍,即根本无法将Rational子类化的能力。重写__new__似乎是一项要求,因为Rational.__new__(cls, *args)返回它所感觉的任何类型的实例,而不是返回cls类型的实例(为什么尝试0失败)。在

我基于提供的参数创建了一个新的Rational并将其存储在MixedNumber中,并且以某种方式透明地传递对MixedNumber没有定义的函数和变量的访问(尝试1、2、3),但是我尝试过的任何方法都没有成功。在

因为我可以让Rational的一个子类在Rational.__new__(cls, *args)实际返回一个有理数(而不是整数、1或0)时正常工作,所以我几乎准备好编写5个独立的类(MixedNumber、MixedRational、MixedInteger、MixedOne、MixedZero),使用MixedNumber.__new__(cls, *args)调用Rational.__new__(cls, *args),然后根据Rational.__new__返回的类型决定实例化哪个混合*类。在

不过,我觉得我必须把这件事复杂化。在

from sympy import *
class MixedNumber(Rational):
    def __new__(cls, *args):
        #Attempt 3
        rational_instance = Rational.__new__(cls, *args)
        rational_instance.__class__ = cls
        return rational_instance

        #Attempt 2
        #rational_instance = Rational.__new__(cls, *args)
        #mixed_instance = object.__new__(cls)
        #mixed_instance.my_rational = rational_instance
        #print("dict")
        #return mixed_instance

        #Attempt 1
        #rational_instance = Rational.__new__(cls, *args)
        #mixed_instance = object.__new__(cls)
        #mixed_instance.__dict__.update(rational_instance.__dict__)
        #return mixed_instance

        #Attempt 0
        #return Rational.__new__(cls, *args)    
    def __init__(self, *args):
        # print(self.__dict__)
        # print(self.my_rational)
        self.my_rational.__init__(*args)
    #Attempt 2  
    #def __getattr__(self, attr):
    #   print("Attr=", attr)
    #   print("Dict=",self.__dict__)
    #   import time
    #   time.sleep(1)
    #   try:
    #       return self.__dict__[attr]
    #   except KeyError:
    #       return getattr(self.my_rational, attr)
x = Rational(0,1)
print(x)
print(type(x))
print(x.p)
print(x.q)
y = Rational(3,1)
print(y)
print(type(y))
print(y.p)
print(y.q)
z = Rational(15,4)
print(z)
print(type(z))
print(z.p)
print(z.q)
x = MixedNumber(0,1)
print(x)
print(type(x))
print(x.p)
print(x.q)
y = MixedNumber(3,1)
print(y)
print(type(y))
print(y.p)
print(y.q)
z = MixedNumber(15,4)
print(z)
print(type(z))
print(z.p)
print(z.q)

Tags: instanceselfnewreturnmytypeargsdict
1条回答
网友
1楼 · 发布于 2024-03-28 21:42:30

我认为试图将Rational子类化是徒劳的。很多SymPy函数都是硬编码来使用Rational的,所以即使您创建了一个成功的子类,您对表达式所做的任何操作都会再次将其移回Rational。在

相反,您应该修改打印机,以便它按您想要的方式打印。根据所使用的打印机,应将该打印机子类化,并重写_print_Rational。参见documentation。既然您提到了latex,您将子类LatexPrinter并重写_print_Rational(self, expr)以不正确的形式打印expr(有理数)。使用self._print递归打印子表达式。在

然后使用YourPrinter().doprint(expr)打印表达式,而不是默认的latex(expr)(这是LatexPrinter().doprint(expr)的简写)。在

子类化打印机时,查看original implementation(latex打印机位于latex.py中)可能会很有用。这是在撰写本文时LatexPrinter._print_Rational的默认实现

def _print_Rational(self, expr):
    if expr.q != 1:
        sign = ""
        p = expr.p
        if expr.p < 0:
            sign = "- "
            p = -p
        return r"%s\frac{%d}{%d}" % (sign, p, expr.q)
    else:
        return self._print(expr.p)

相关问题 更多 >