如何在python对象创建过程中处理错误

时间:2017-04-05 11:47:04

标签: python python-3.x fractions

我正在尝试写一个类来帮助我输出混合分数。

此代码适用于我的目的

class mixed_fraction():
    from fractions import Fraction
    '''Returns mixed fractions in tuple format
    (whole_part, numerator, denominator)
    '''
    def __init__(self, numerator = 0, denominator = 1):
        self.numerator = numerator
        self.denominator = denominator
    def mixed(self):
        if self.denominator == 0:
            return 'Denominator cannot be Zero'
        quotient = int(self.numerator/self.denominator)
        remain = self.numerator - (self.denominator * quotient)
        frac = Fraction(remain, self.denominator)
        return (quotient, frac.numerator, frac.denominator)

示例输入

print(mixed_fraction(3, 2).mixed())
print(mixed_fraction(1, 5).mixed())
print(mixed_fraction(1, 0).mixed())
print(mixed_fraction().mixed())
print(mixed_fraction(7, 2).mixed())
print(mixed_fraction(769, 17).mixed())
print(mixed_fraction(384, 256).mixed())

输出

(1, 1, 2)
(0, 1, 5)
Denominator cannot be Zero
(0, 0, 1)
(3, 1, 2)
(45, 4, 17)
(1, 1, 2)

但我希望能够在创建对象时调出零误差,因为首先创建一个零除数的分数是没有意义的。所以我需要帮助按时捕获错误。

class mixed_fraction():
    from fractions import Fraction
    '''Returns mixed fractions in tuple format
    (whole_part, numerator, denominator)
    '''
    def __init__(self, numerator = 0, denominator = 1):
        self.numerator = numerator
        self.denominator = denominator
        if denominator == 0:
            return 'Denominator cannot be Zero'
    def mixed(self):
        quotient = int(self.numerator/self.denominator)
        remain = self.numerator - (self.denominator * quotient)
        frac = Fraction(remain, self.denominator)
        return (quotient, frac.numerator, frac.denominator)

问题是__init__必须返回None。所以我对如何解决这个问题感到茫然

2 个答案:

答案 0 :(得分:3)

如果要在Python中生成错误,则不会返回值:引发错误。

在这种情况下,最合适的是ZeroDivisionError:

def __init__(self, numerator = 0, denominator = 1):
    self.numerator = numerator
    self.denominator = denominator
    if denominator == 0:
        raise ZeroDivisionError('Denominator cannot be Zero!')

ZeroDivisionError本身就是“ArithmeticError”的一个特殊化 - 但你可以通过对它进行子类化来进一步调整错误:

class ZeroDenominatorError(ZeroDivisionError): 
    pass

它的主要优点是程序流程可以通过层来实现 使用try ... except块无法正确处理错误的代码 - 直到您捕获它的位置 - 否则您必须在所有位置放置if语句您实例化类的位置,以检查返回值的类型。

所以 - 这是正确的方式来处理它。现在,根据设计,可能需要让类的实例化失败并返回另一个值(“None”将比错误消息更好 - 产生错误,只是引发异常)。在这种情况下,您应该使用__new__方法而不是__init__。与__init__不同,它必须返回新创建的实例。 (并且它还必须通过正确调用超类的__new__方法来创建该新实例):

from fractions import Fraction

class MixedFraction(Fraction):
    def __new__(cls, numerator=0, denominator=1):
        if not denominator:
            return None
        instance = super().__new__(cls, numerator, denominator)
        return instance
    def mixed(self):
        quotient = self.numerator // self.denominator
        remain = self.numerator - (self.denominator * quotient)
        return (quotient, remain, self.denominator)

至于Hilliad在他的回答中提出的建议,这直接来自“Fraction” - 这意味着它可以在任何使用Fraction的地方使用,但它有额外的“混合”方法。请注意,如果您正在操作分子和分母参数,则继承自Fraction将要求您编写__new__而不是__init__:它们在实例化时设置在对象中,以native({{ 1}})代码,无法进一步更改。

答案 1 :(得分:2)

如果用户提供的对您的给定对象没有意义,引发ValueError 而不是完成创建:

def __init__(self, numerator = 0, denominator = 1):
    self.numerator = numerator
    if self.denominator == 0:
        raise ValueError("argument 'denominator' cannot be zero")
    self.denominator = denominator

这是应该处理这种情况的标准方法。

顺便说一下,两件小事:

  • 使用驼峰案例作为您的班级名称,而不是mixed_fraction使用MixedFraction。 (小的一边:括号不是必需的)
  • 不要在类体中导入,在模块范围外导入它。
  • 如果您计划在希望您的对象行为像Fraction的区域中使用此功能,请考虑从Fraction继承。