【问题标题】:Special Values of a Class类的特殊值
【发布时间】:2021-04-04 02:14:17
【问题描述】:

现在我正在创建一个代表闭区间的类。它的核心功能是提供一个intersect 方法。

class Interval:
    def __init__(self, a, b):
        # check a <= b otherwise swap
        self.a = a
        self.b = b
    def intersect(self, other):
        a = self.a if self.a > other.a else other.a
        b = self.b if self.b < other.b else other.b
        if b < a:
            # return some value representing an empty interval, providing the intersect method
        return Intervall(a,b)

应该可以表示特殊值,例如所有点 [-oo,oo] 或空集 {}。它仍然服务于intersect 方法。我目前的方法是创建一个新类,但这似乎有点乏味。

class EmptyInterval:
    def intersect(self, other):
        return self

假设那些特殊值的 intersect 方法优先,我会在 Intervall 类的方法之前添加:

class Intervall:
    ...
    def intersect(self,other):
        if not isinstance(self, other):
            other.intersect(self)
        ...

澄清一下 - 以下内容应该是合法的:

a = Intervall(1,2)
b = Intervall(3,4)

c = a.intersect(b)  # resulting in an empty interval

c.intersect(a)      # resulting again in an empty interval

是否有一些优雅/更蟒蛇/不那么令人作呕的丑陋方式来实现这种行为?

首先我想到了继承,但这似乎很不合适,因为这些特殊值应该具有优先级;即我不知道如何通过继承来实现它。

【问题讨论】:

    标签: python python-3.x oop inheritance


    【解决方案1】:

    在你的类中定义几个特殊函数Interval

    @staticmethod
    def everything():
        return Interval(-math.inf, math.inf)
    
    @staticmethod
    def nothing():
        return Interval(math.nan, math.nan)
    

    您可能会发现这样写nothing() 更自然:

        return Interval(0, 0)
    

    或者这个:

        return Interval(math.inf, math.inf)
    

    这取决于您的其他代码,以及您认为表示空区间的最自然方式。请注意,与 NAN 进行任何较小或较大的比较都会返回 false,因此这可能会对您决定表示空区间的方式产生一些影响(例如,nothing().intersect(nothing()) 应该是 true 还是 false?)。

    【讨论】:

    • 感谢您的回答! nothing().intersect(nothing()) 都不应该返回 nothing(),Interval(math.nan, math.nan) 就是这种情况。我自己想出了一个可能的解决方案,稍后会发布。也许你可以对此发表评论。之后我会关闭线程。
    【解决方案2】:

    也许这可能是另一种解决方案:

    我可以传递一个元组 (a,b),而不是单独传递 a,b。此外,我可以将几个单例声明为类变量。在实例化期间,我会传递该单例,并且只需要检查该值是否是单例之一并采取相应的行动。

    class Interval:
        EMPTY = object()
        EVERYTHING = object()
        def __init__(self, bounds):
            self.bound = bounds
    
        def intersect(self, other):
            if self.bounds == self.EMPTY or other.bounds == self.EMPTY:
                return Interval(self.EMPTY)
    
            ...
     
            if b < a:
                return Interval(self.EMPTY)
    
            return Interval((a,b))
    

    我想这可能比约翰的答案更不容易出错,因为 math.inf 和/或 math.nan 强加的一般行为。此外,它还允许严格禁止传递这些值,因为 Interval(math.nan, 1) 将是无意义的。

    但在更复杂的环境中实施可能会更加努力。

    【讨论】:

    • 这样做会失去所有类型安全性:EMPTY 不是Interval 的实例。也许这对你来说没问题,但对某些人来说,这会破坏交易。
    • 舒尔这是真的。但正如我所说,我更愿意指定我的班级将有的所有行为。无论如何:感谢您的宝贵时间!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多